From: izsh.f0f Date: Thu, 4 Feb 2010 01:27:07 +0000 (+0000) Subject: Client cleanup and restructuring. Stage 1... X-Git-Tag: v1.0.0~392 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/7fe9b0b742d7dae9c5af1d292d11840b5c3cbfae Client cleanup and restructuring. Stage 1... Next Step is refactoring some of the giant functions which are just copy/paste of some other ones with just a few line changes, removing unnecessary 'goto' etc. The MS Windows version is broken with this commit but will be fixed soon. Everything can't be done all at once :P The commands are now hierarchical, for example: "hf 14a read" vs. "hf 14b read". You can also request help: "hf help", "data help", "hf 15 help" etc. Indents are now space-based, not tab-based anymore. Hopefully no one will be trolling about it, considering the suicide-prone work being done here ;) client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h, client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h, client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c, client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h, client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h, client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h, client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h, client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h, client/cmdhflegic.c, client/cmdhflegic.c: New files. client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c, client/proxmark3.h, client/Makefile: Update accordingly. client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes. client/translate.h, client/command.c, client/gui.c, client/usb.c, client/prox.h: Remove. include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd. common/crc16.h: New file. common/crc16.c: Modify accordingly. common/iso14443crc.h: New file. common/iso14443_crc.c: Rename to common/iso14443crc.c: and modify accordingly. armsrc/lfops.c, armsrc/iso14443.c, armsrc/iso14443a.c: include .h files from the common directory instead of including the c files. common/Makefile.common, armsrc/Makefile: Modify accordingly. --- diff --git a/armsrc/Makefile b/armsrc/Makefile index 227f3747..a6b2fcc8 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -24,6 +24,8 @@ THUMBSRC = start.c \ # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ legicrf.c \ + iso14443crc.c \ + crc16.c \ $(SRC_ISO14443a) \ $(SRC_ISO14443b) \ crc.c diff --git a/armsrc/iso14443.c b/armsrc/iso14443.c index dc1dbf12..b20d1be9 100644 --- a/armsrc/iso14443.c +++ b/armsrc/iso14443.c @@ -6,7 +6,7 @@ //----------------------------------------------------------------------------- #include #include "apps.h" -#include "../common/iso14443_crc.c" +#include "iso14443crc.h" //static void GetSamplesFor14443(BOOL weTx, int n); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a7d09459..02d912e7 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- #include #include "apps.h" -#include "../common/iso14443_crc.c" +#include "iso14443crc.h" static BYTE *trace = (BYTE *) BigBuf; static int traceLen = 0; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index a6216eec..a7e1f1df 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -7,7 +7,7 @@ #include #include "apps.h" #include "hitag2.h" -#include "../common/crc16.c" +#include "crc16.h" void AcquireRawAdcSamples125k(BOOL at134khz) { diff --git a/client/Makefile b/client/Makefile index 8bbc0273..48ddffd2 100644 --- a/client/Makefile +++ b/client/Makefile @@ -1,15 +1,38 @@ WINCC=c:\mingw\bin\gcc - #COMMON_FLAGS = -m32 +VPATH = ../common + LDLIBS = -L/opt/local/lib -L/usr/local/lib -lusb -lreadline -lpthread LDFLAGS = $(COMMON_FLAGS) -CFLAGS = -I. -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) -g3 +CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) -g3 WINLIBS = -lgdi32 -lsetupapi CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) +CMDSRCS = \ + crc16.c \ + iso14443crc.c \ + data.c \ + graph.c \ + ui.c \ + cmddata.c \ + cmdhf.c \ + cmdhf14a.c \ + cmdhf14b.c \ + cmdhf15.c \ + cmdhflegic.c \ + cmdhw.c \ + cmdlf.c \ + cmdlfem4x.c \ + cmdlfhid.c \ + cmdlfti.c \ + cmdparser.c \ + cmdmain.c + +CMDOBJS = $(CMDSRCS:.c=.o) + ifeq ($(shell echo ""),) ifeq ($(shell uname),Darwin) @@ -29,7 +52,7 @@ endif RM = rm -f BINS = proxmark3 snooper cli flasher -CLEAN = cli flasher proxmark3 snooper *.o *.moc.cpp +CLEAN = cli flasher proxmark3 snooper *.o $(CMDOBJS) *.moc.cpp else RM = del BINS = prox.exe @@ -41,19 +64,17 @@ all: $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: snooper cli flasher -prox.exe: prox.c wingui.c command.c flash.c - $(WINCC) $(CFLAGS) $(DEFINES) -o prox.exe prox.c wingui.c command.c flash.c $(WINLIBS) +prox.exe: prox.c wingui.c $(CMDSRCS) flash.c + $(WINCC) $(CFLAGS) $(DEFINES) -o prox.exe prox.c wingui.c $(CMDSRCS) flash.c $(WINLIBS) proxmark3: LDLIBS+=$(QTLDLIBS) -proxmark3: proxmark3.o gui.o command.o usb.o $(QTGUI) - -command.o: command.c +proxmark3: proxmark3.o $(CMDOBJS) proxusb.o $(QTGUI) -snooper: snooper.o gui.o command.o usb.o guidummy.o +snooper: snooper.o $(CMDOBJS) proxusb.o guidummy.o -cli: cli.o gui.o command.o usb.o guidummy.o +cli: cli.o $(CMDOBJS) proxusb.o guidummy.o -flasher: flash.o flasher.o usb.o +flasher: flash.o flasher.o proxusb.o proxguiqt.moc.cpp: proxguiqt.h $(MOC) -o$@ $^ diff --git a/client/cli.c b/client/cli.c index f6162227..25567677 100644 --- a/client/cli.c +++ b/client/cli.c @@ -1,60 +1,49 @@ -#include #include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "proxmark3.h" +#include "ui.h" +#include "proxusb.h" +#include "cmdmain.h" #define HANDLE_ERROR if (error_occured) { \ - error_occured = 0;\ - break;\ + error_occured = 0;\ + break;\ } int main(int argc, char **argv) { - if(argc != 3 && argc != 4) - { - printf("\n\tusage: cli [logfile (default cli.log)]\n"); - printf("\n"); - printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); - printf("\n"); - return -1; - } - - usb_init(); - if (argc == 4) - setlogfilename(argv[3]); - else - setlogfilename("cli.log"); - - return_on_error = 1; - - while(1) { - while(!(devh=OpenProxmark(0))) { sleep(1); } - - while(1) { - UsbCommand cmdbuf; - int i; - - CommandReceived(argv[1]); - HANDLE_ERROR - - ReceiveCommand(&cmdbuf); - HANDLE_ERROR - for (i=0; i<5; i++) { - ReceiveCommandPoll(&cmdbuf); - } - HANDLE_ERROR - - CommandReceived(argv[2]); - HANDLE_ERROR - } - } - - CloseProxmark(); - return 0; + if (argc != 3 && argc != 4) + { + printf("\n\tusage: cli [logfile (default cli.log)]\n"); + printf("\n"); + printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); + printf("\n"); + return -1; + } + + usb_init(); + if (argc == 4) + SetLogFilename(argv[3]); + else + SetLogFilename("cli.log"); + + return_on_error = 1; + + while (1) { + while (!OpenProxmark(0)) { sleep(1); } + while (1) { + UsbCommand cmdbuf; + CommandReceived(argv[1]); + HANDLE_ERROR; + ReceiveCommand(&cmdbuf); + HANDLE_ERROR; + for (int i = 0; i < 5; ++i) { + ReceiveCommandPoll(&cmdbuf); + } + HANDLE_ERROR; + CommandReceived(argv[2]); + HANDLE_ERROR; + } + } + + CloseProxmark(); + return 0; } diff --git a/client/cmddata.c b/client/cmddata.c new file mode 100644 index 00000000..e3a8c54c --- /dev/null +++ b/client/cmddata.c @@ -0,0 +1,910 @@ +#include +#include +#include +#include +#include "proxusb.h" +#include "data.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmdmain.h" +#include "cmddata.h" + +static int CmdHelp(const char *Cmd); + +int CmdAmp(const char *Cmd) +{ + int i, rising, falling; + int max = INT_MIN, min = INT_MAX; + + for (i = 10; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] > max) + max = GraphBuffer[i]; + if (GraphBuffer[i] < min) + min = GraphBuffer[i]; + } + + if (max != min) { + rising = falling= 0; + for (i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i + 1] < GraphBuffer[i]) { + if (rising) { + GraphBuffer[i] = max; + rising = 0; + } + falling = 1; + } + if (GraphBuffer[i + 1] > GraphBuffer[i]) { + if (falling) { + GraphBuffer[i] = min; + falling = 0; + } + rising= 1; + } + } + } + RepaintGraphWindow(); + return 0; +} + +/* + * Generic command to demodulate ASK. + * + * Argument is convention: positive or negative (High mod means zero + * or high mod means one) + * + * Updates the Graph trace with 0/1 values + * + * Arguments: + * c : 0 or 1 + */ +int Cmdaskdemod(const char *Cmd) +{ + int i; + int c, high = 0, low = 0; + + // TODO: complain if we do not give 2 arguments here ! + // (AL - this doesn't make sense! we're only using one argument!!!) + sscanf(Cmd, "%i", &c); + + /* Detect high and lows and clock */ + // (AL - clock???) + for (i = 0; i < GraphTraceLen; ++i) + { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + if (c != 0 && c != 1) { + PrintAndLog("Invalid argument: %s", Cmd); + return 0; + } + + if (GraphBuffer[0] > 0) { + GraphBuffer[0] = 1-c; + } else { + GraphBuffer[0] = c; + } + for (i = 1; i < GraphTraceLen; ++i) { + /* Transitions are detected at each peak + * Transitions are either: + * - we're low: transition if we hit a high + * - we're high: transition if we hit a low + * (we need to do it this way because some tags keep high or + * low for long periods, others just reach the peak and go + * down) + */ + if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) { + GraphBuffer[i] = 1 - c; + } else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){ + GraphBuffer[i] = c; + } else { + /* No transition */ + GraphBuffer[i] = GraphBuffer[i - 1]; + } + } + RepaintGraphWindow(); + return 0; +} + +int CmdAutoCorr(const char *Cmd) +{ + static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; + + int window = atoi(Cmd); + + if (window == 0) { + PrintAndLog("needs a window"); + return 0; + } + if (window >= GraphTraceLen) { + PrintAndLog("window must be smaller than trace (%d samples)", + GraphTraceLen); + return 0; + } + + PrintAndLog("performing %d correlations", GraphTraceLen - window); + + for (int i = 0; i < GraphTraceLen - window; ++i) { + int sum = 0; + for (int j = 0; j < window; ++j) { + sum += (GraphBuffer[j]*GraphBuffer[i + j]) / 256; + } + CorrelBuffer[i] = sum; + } + GraphTraceLen = GraphTraceLen - window; + memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen * sizeof (int)); + + RepaintGraphWindow(); + return 0; +} + +int CmdBitsamples(const char *Cmd) +{ + int cnt = 0; + int n = 3072; + + for (int i = 0; i < n; i += 12) { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; + SendCommand(&c); + WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + + for (int j = 0; j < 48; j++) { + for (int k = 0; k < 8; k++) { + if(sample_buf[j] & (1 << (7 - k))) { + GraphBuffer[cnt++] = 1; + } else { + GraphBuffer[cnt++] = 0; + } + } + } + } + GraphTraceLen = cnt; + RepaintGraphWindow(); + return 0; +} + +/* + * Convert to a bitstream + */ +int CmdBitstream(const char *Cmd) +{ + int i, j; + int bit; + int gtl; + int clock; + int low = 0; + int high = 0; + int hithigh, hitlow, first; + + /* Detect high and lows and clock */ + for (i = 0; i < GraphTraceLen; ++i) + { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + + /* Get our clock */ + clock = GetClock(Cmd, high, 1); + gtl = ClearGraph(0); + + bit = 0; + for (i = 0; i < (int)(gtl / clock); ++i) + { + hithigh = 0; + hitlow = 0; + first = 1; + /* Find out if we hit both high and low peaks */ + for (j = 0; j < clock; ++j) + { + if (GraphBuffer[(i * clock) + j] == high) + hithigh = 1; + else if (GraphBuffer[(i * clock) + j] == low) + hitlow = 1; + /* it doesn't count if it's the first part of our read + because it's really just trailing from the last sequence */ + if (first && (hithigh || hitlow)) + hithigh = hitlow = 0; + else + first = 0; + + if (hithigh && hitlow) + break; + } + + /* If we didn't hit both high and low peaks, we had a bit transition */ + if (!hithigh || !hitlow) + bit ^= 1; + + AppendGraph(0, clock, bit); +// for (j = 0; j < (int)(clock/2); j++) +// GraphBuffer[(i * clock) + j] = bit ^ 1; +// for (j = (int)(clock/2); j < clock; j++) +// GraphBuffer[(i * clock) + j] = bit; + } + + RepaintGraphWindow(); + return 0; +} + +int CmdBuffClear(const char *Cmd) +{ + UsbCommand c = {CMD_BUFF_CLEAR}; + SendCommand(&c); + ClearGraph(true); + return 0; +} + +int CmdDec(const char *Cmd) +{ + for (int i = 0; i < (GraphTraceLen / 2); ++i) + GraphBuffer[i] = GraphBuffer[i * 2]; + GraphTraceLen /= 2; + PrintAndLog("decimated by 2"); + RepaintGraphWindow(); + return 0; +} + +/* Print our clock rate */ +int CmdDetectClockRate(const char *Cmd) +{ + int clock = DetectClock(0); + PrintAndLog("Auto-detected clock rate: %d", clock); + return 0; +} + +int CmdFSKdemod(const char *Cmd) +{ + static const int LowTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 + }; + static const int HighTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, -1, + }; + + int lowLen = sizeof (LowTone) / sizeof (int); + int highLen = sizeof (HighTone) / sizeof (int); + int convLen = (highLen > lowLen) ? highLen : lowLen; + uint32_t hi = 0, lo = 0; + + int i, j; + int minMark = 0, maxMark = 0; + + for (i = 0; i < GraphTraceLen - convLen; ++i) { + int lowSum = 0, highSum = 0; + + for (j = 0; j < lowLen; ++j) { + lowSum += LowTone[j]*GraphBuffer[i+j]; + } + for (j = 0; j < highLen; ++j) { + highSum += HighTone[j] * GraphBuffer[i + j]; + } + lowSum = abs(100 * lowSum / lowLen); + highSum = abs(100 * highSum / highLen); + GraphBuffer[i] = (highSum << 16) | lowSum; + } + + for(i = 0; i < GraphTraceLen - convLen - 16; ++i) { + int lowTot = 0, highTot = 0; + // 10 and 8 are f_s divided by f_l and f_h, rounded + for (j = 0; j < 10; ++j) { + lowTot += (GraphBuffer[i+j] & 0xffff); + } + for (j = 0; j < 8; j++) { + highTot += (GraphBuffer[i + j] >> 16); + } + GraphBuffer[i] = lowTot - highTot; + if (GraphBuffer[i] > maxMark) maxMark = GraphBuffer[i]; + if (GraphBuffer[i] < minMark) minMark = GraphBuffer[i]; + } + + GraphTraceLen -= (convLen + 16); + RepaintGraphWindow(); + + // Find bit-sync (3 lo followed by 3 high) + int max = 0, maxPos = 0; + for (i = 0; i < 6000; ++i) { + int dec = 0; + for (j = 0; j < 3 * lowLen; ++j) { + dec -= GraphBuffer[i + j]; + } + for (; j < 3 * (lowLen + highLen ); ++j) { + dec += GraphBuffer[i + j]; + } + if (dec > max) { + max = dec; + maxPos = i; + } + } + + // place start of bit sync marker in graph + GraphBuffer[maxPos] = maxMark; + GraphBuffer[maxPos + 1] = minMark; + + maxPos += j; + + // place end of bit sync marker in graph + GraphBuffer[maxPos] = maxMark; + GraphBuffer[maxPos+1] = minMark; + + PrintAndLog("actual data bits start at sample %d", maxPos); + PrintAndLog("length %d/%d", highLen, lowLen); + + uint8_t bits[46]; + bits[sizeof(bits)-1] = '\0'; + + // find bit pairs and manchester decode them + for (i = 0; i < arraylen(bits) - 1; ++i) { + int dec = 0; + for (j = 0; j < lowLen; ++j) { + dec -= GraphBuffer[maxPos + j]; + } + for (; j < lowLen + highLen; ++j) { + dec += GraphBuffer[maxPos + j]; + } + maxPos += j; + // place inter bit marker in graph + GraphBuffer[maxPos] = maxMark; + GraphBuffer[maxPos + 1] = minMark; + + // hi and lo form a 64 bit pair + hi = (hi << 1) | (lo >> 31); + lo = (lo << 1); + // store decoded bit as binary (in hi/lo) and text (in bits[]) + if(dec < 0) { + bits[i] = '1'; + lo |= 1; + } else { + bits[i] = '0'; + } + } + PrintAndLog("bits: '%s'", bits); + PrintAndLog("hex: %08x %08x", hi, lo); + return 0; +} + +int CmdGrid(const char *Cmd) +{ + sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); + RepaintGraphWindow(); + return 0; +} + +int CmdHexsamples(const char *Cmd) +{ + int n; + int requested = 0; + int offset = 0; + sscanf(Cmd, "%i %i", &requested, &offset); + if (offset % 4 != 0) { + PrintAndLog("Offset must be a multiple of 4"); + return 0; + } + offset = offset/4; + + int delivered = 0; + + if (requested == 0) { + n = 12; + requested = 12; + } else { + n = requested/4; + } + + for (int i = offset; i < n+offset; i += 12) { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; + SendCommand(&c); + WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + for (int j = 0; j < 48; j += 8) { + PrintAndLog("%02x %02x %02x %02x %02x %02x %02x %02x", + sample_buf[j+0], + sample_buf[j+1], + sample_buf[j+2], + sample_buf[j+3], + sample_buf[j+4], + sample_buf[j+5], + sample_buf[j+6], + sample_buf[j+7], + sample_buf[j+8] + ); + delivered += 8; + if (delivered >= requested) + break; + } + if (delivered >= requested) + break; + } + return 0; +} + +int CmdHFSamples(const char *Cmd) +{ + int cnt = 0; + int n = strtol(Cmd, NULL, 0); + + if(n == 0) { + n = 1000; + } else { + n/= 4; + } + + for (int i = 0; i < n; i += 12) { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; + SendCommand(&c); + WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + for (int j = 0; j < 48; ++j) { + GraphBuffer[cnt++] = (int)(sample_buf[j]); + } + } + GraphTraceLen = cnt; + RepaintGraphWindow(); + return 0; +} + +int CmdHide(const char *Cmd) +{ + HideGraphWindow(); + return 0; +} + +int CmdHpf(const char *Cmd) +{ + int i; + int accum = 0; + + for (i = 10; i < GraphTraceLen; ++i) + accum += GraphBuffer[i]; + accum /= (GraphTraceLen - 10); + for (i = 0; i < GraphTraceLen; ++i) + GraphBuffer[i] -= accum; + + RepaintGraphWindow(); + return 0; +} + +int CmdLFSamples(const char *Cmd) +{ + int cnt = 0; + int n; + + n = strtol(Cmd, NULL, 0); + if (n == 0) n = 128; + if (n > 16000) n = 16000; + + PrintAndLog("Reading %d samples\n", n); + for (int i = 0; i < n; i += 12) { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; + SendCommand(&c); + WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + for (int j = 0; j < 48; j++) { + GraphBuffer[cnt++] = ((int)sample_buf[j]) - 128; + } + } + PrintAndLog("Done!\n"); + GraphTraceLen = n*4; + RepaintGraphWindow(); + return 0; +} + +int CmdLoad(const char *Cmd) +{ + FILE *f = fopen(Cmd, "r"); + if (!f) { + PrintAndLog("couldn't open '%s'", Cmd); + return 0; + } + + GraphTraceLen = 0; + char line[80]; + while (fgets(line, sizeof (line), f)) { + GraphBuffer[GraphTraceLen] = atoi(line); + GraphTraceLen++; + } + fclose(f); + PrintAndLog("loaded %d samples", GraphTraceLen); + RepaintGraphWindow(); + return 0; +} + +int CmdLtrim(const char *Cmd) +{ + int ds = atoi(Cmd); + + for (int i = ds; i < GraphTraceLen; ++i) + GraphBuffer[i-ds] = GraphBuffer[i]; + GraphTraceLen -= ds; + + RepaintGraphWindow(); + return 0; +} + +/* + * 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) + * Typical values can be 64, 32, 128... + */ +int CmdManchesterDemod(const char *Cmd) +{ + int i, j, invert= 0; + int bit; + int clock; + int lastval; + int low = 0; + int high = 0; + int hithigh, hitlow, first; + int lc = 0; + int bitidx = 0; + int bit2idx = 0; + int warnings = 0; + + /* check if we're inverting output */ + if (*Cmd == 'i') + { + PrintAndLog("Inverting output"); + invert = 1; + do + ++Cmd; + while(*Cmd == ' '); // in case a 2nd argument was given + } + + /* 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 high and lows */ + for (i = 0; i < GraphTraceLen; i++) + { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + + /* Get our clock */ + clock = GetClock(Cmd, high, 1); + + int tolerance = clock/4; + + /* Detect first transition */ + /* Lo-Hi (arbitrary) */ + /* skip to the first high */ + for (i= 0; i < GraphTraceLen; i++) + if (GraphBuffer[i] == high) + break; + /* now look for the first low */ + for (; i < GraphTraceLen; i++) + { + if (GraphBuffer[i] == low) + { + lastval = i; + break; + } + } + + /* If we're not working with 1/0s, demod based off clock */ + if (high != 1) + { + bit = 0; /* We assume the 1st bit is zero, it may not be + * the case: this routine (I think) has an init problem. + * Ed. + */ + for (; i < (int)(GraphTraceLen / clock); i++) + { + hithigh = 0; + hitlow = 0; + first = 1; + + /* Find out if we hit both high and low peaks */ + for (j = 0; j < clock; j++) + { + if (GraphBuffer[(i * clock) + j] == high) + hithigh = 1; + else if (GraphBuffer[(i * clock) + j] == low) + hitlow = 1; + + /* it doesn't count if it's the first part of our read + because it's really just trailing from the last sequence */ + if (first && (hithigh || hitlow)) + hithigh = hitlow = 0; + else + first = 0; + + if (hithigh && hitlow) + break; + } + + /* If we didn't hit both high and low peaks, we had a bit transition */ + if (!hithigh || !hitlow) + bit ^= 1; + + BitStream[bit2idx++] = bit ^ invert; + } + } + + /* standard 1/0 bitstream */ + else + { + + /* Then detect duration between 2 successive transitions */ + 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) ) { + PrintAndLog("Error: the clock you gave is probably wrong, aborting."); + return 0; + } + // Then switch depending on lc length: + // Tolerance is 1/4 of clock rate (arbitrary) + if (abs(lc-clock/2) < tolerance) { + // Short pulse : either "1" or "0" + BitStream[bitidx++]=GraphBuffer[i-1]; + } else if (abs(lc-clock) < tolerance) { + // Long pulse: either "11" or "00" + BitStream[bitidx++]=GraphBuffer[i-1]; + BitStream[bitidx++]=GraphBuffer[i-1]; + } else { + // Error + warnings++; + PrintAndLog("Warning: Manchester decode error for pulse width detection."); + PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)"); + + if (warnings > 10) + { + PrintAndLog("Error: too many detection errors, aborting."); + return 0; + } + } + } + } + + // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream + // 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 ^ invert; + } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) { + BitStream[bit2idx++] = 0 ^ invert; + } else { + // We cannot end up in this state, this means we are unsynchronized, + // move up 1 bit: + i++; + warnings++; + PrintAndLog("Unsynchronized, resync..."); + PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)"); + + if (warnings > 10) + { + PrintAndLog("Error: too many decode errors, aborting."); + return 0; + } + } + } + } + + PrintAndLog("Manchester decoded bitstream"); + // Now output the bitstream to the scrollback by line of 16 bits + for (i = 0; i < (bit2idx-16); i+=16) { + PrintAndLog("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", + 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]); + } + return 0; +} + +/* Modulate our data into manchester */ +int CmdManchesterMod(const char *Cmd) +{ + int i, j; + int clock; + int bit, lastbit, wave; + + /* Get our clock */ + clock = GetClock(Cmd, 0, 1); + + wave = 0; + lastbit = 1; + for (i = 0; i < (int)(GraphTraceLen / clock); i++) + { + bit = GraphBuffer[i * clock] ^ 1; + + for (j = 0; j < (int)(clock/2); j++) + GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave; + for (j = (int)(clock/2); j < clock; j++) + GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1; + + /* Keep track of how we start our wave and if we changed or not this time */ + wave ^= bit ^ lastbit; + lastbit = bit; + } + + RepaintGraphWindow(); + return 0; +} + +int CmdNorm(const char *Cmd) +{ + int i; + int max = INT_MIN, min = INT_MAX; + + for (i = 10; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] > max) + max = GraphBuffer[i]; + if (GraphBuffer[i] < min) + min = GraphBuffer[i]; + } + + if (max != min) { + for (i = 0; i < GraphTraceLen; ++i) { + GraphBuffer[i] = (GraphBuffer[i] - ((max + min) / 2)) * 1000 / + (max - min); + } + } + RepaintGraphWindow(); + return 0; +} + +int CmdPlot(const char *Cmd) +{ + ShowGraphWindow(); + return 0; +} + +int CmdSave(const char *Cmd) +{ + FILE *f = fopen(Cmd, "w"); + if(!f) { + PrintAndLog("couldn't open '%s'", Cmd); + return 0; + } + int i; + for (i = 0; i < GraphTraceLen; i++) { + fprintf(f, "%d\n", GraphBuffer[i]); + } + fclose(f); + PrintAndLog("saved to '%s'", Cmd); + return 0; +} + +int CmdScale(const char *Cmd) +{ + CursorScaleFactor = atoi(Cmd); + if (CursorScaleFactor == 0) { + PrintAndLog("bad, can't have zero scale"); + CursorScaleFactor = 1; + } + RepaintGraphWindow(); + return 0; +} + +int CmdThreshold(const char *Cmd) +{ + int threshold = atoi(Cmd); + + for (int i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] >= threshold) + GraphBuffer[i] = 1; + else + GraphBuffer[i] =- 1; + } + RepaintGraphWindow(); + return 0; +} + +int CmdZerocrossings(const char *Cmd) +{ + // Zero-crossings aren't meaningful unless the signal is zero-mean. + CmdHpf(""); + + int sign = 1; + int zc = 0; + int lastZc = 0; + + for (int i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] * sign >= 0) { + // No change in sign, reproduce the previous sample count. + zc++; + GraphBuffer[i] = lastZc; + } else { + // Change in sign, reset the sample count. + sign = -sign; + GraphBuffer[i] = lastZc; + if (sign > 0) { + lastZc = zc; + zc = 0; + } + } + } + + RepaintGraphWindow(); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"amp", CmdAmp, 1, "Amplify peaks"}, + {"askdemod", Cmdaskdemod, 1, "<0|1> -- Attempt to demodulate simple ASK tags"}, + {"autocorr", CmdAutoCorr, 1, " -- Autocorrelation over window"}, + {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, + {"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"}, + {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, + {"dec", CmdDec, 1, "Decimate samples"}, + {"detectclock", CmdDetectClockRate, 1, "Detect clock rate"}, + {"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"}, + {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, + {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"hfsamples", CmdHFSamples, 0, "[nb of samples] Get raw samples for HF tag"}, + {"hide", CmdHide, 1, "Hide graph window"}, + {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, + {"lfsamples", CmdLFSamples, 0, "[128 - 16000] -- Get raw samples for LF tag"}, + {"load", CmdLoad, 1, " -- Load trace (to graph window"}, + {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, + {"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, + {"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"}, + {"norm", CmdNorm, 1, "Normalize max/min to +/-500"}, + {"plot", CmdPlot, 1, "Show graph window"}, + {"save", CmdSave, 1, " -- Save trace (from graph window)"}, + {"scale", CmdScale, 1, " -- Set cursor display scale"}, + {"threshold", CmdThreshold, 1, "Maximize/minimize every value in the graph window depending on threshold"}, + {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, + {NULL, NULL, 0, NULL} +}; + +int CmdData(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmddata.h b/client/cmddata.h new file mode 100644 index 00000000..fd40df1e --- /dev/null +++ b/client/cmddata.h @@ -0,0 +1,32 @@ +#ifndef CMDDATA_H__ +#define CMDDATA_H__ + +int CmdData(const char *Cmd); + +int CmdAmp(const char *Cmd); +int Cmdaskdemod(const char *Cmd); +int CmdAutoCorr(const char *Cmd); +int CmdBitsamples(const char *Cmd); +int CmdBitstream(const char *Cmd); +int CmdBuffClear(const char *Cmd); +int CmdDec(const char *Cmd); +int CmdDetectClockRate(const char *Cmd); +int CmdFSKdemod(const char *Cmd); +int CmdGrid(const char *Cmd); +int CmdHexsamples(const char *Cmd); +int CmdHFSamples(const char *Cmd); +int CmdHide(const char *Cmd); +int CmdHpf(const char *Cmd); +int CmdLFSamples(const char *Cmd); +int CmdLoad(const char *Cmd); +int CmdLtrim(const char *Cmd); +int CmdManchesterDemod(const char *Cmd); +int CmdManchesterMod(const char *Cmd); +int CmdNorm(const char *Cmd); +int CmdPlot(const char *Cmd); +int CmdSave(const char *Cmd); +int CmdScale(const char *Cmd); +int CmdThreshold(const char *Cmd); +int CmdZerocrossings(const char *Cmd); + +#endif diff --git a/client/cmdhf.c b/client/cmdhf.c new file mode 100644 index 00000000..7e3a662b --- /dev/null +++ b/client/cmdhf.c @@ -0,0 +1,41 @@ +#include +#include "proxusb.h" +#include "graph.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdhf.h" +#include "cmdhf14a.h" +#include "cmdhf14b.h" +#include "cmdhf15.h" +#include "cmdhflegic.h" + +static int CmdHelp(const char *Cmd); + +int CmdHFTune(const char *Cmd) +{ + UsbCommand c={CMD_MEASURE_ANTENNA_TUNING_HF}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"14a", CmdHF14A, 1, "ISO14443A RFIDs"}, + {"14b", CmdHF14B, 1, "ISO14443B RFIDs"}, + {"15", CmdHF15, 1, "ISO15693 RFIDs"}, + {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHF(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhf.h b/client/cmdhf.h new file mode 100644 index 00000000..317ab4a7 --- /dev/null +++ b/client/cmdhf.h @@ -0,0 +1,8 @@ +#ifndef CMDHF_H__ +#define CMDHF_H__ + +int CmdHF(const char *Cmd); + +int CmdHFTune(const char *Cmd); + +#endif diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c new file mode 100644 index 00000000..ebf0ea4a --- /dev/null +++ b/client/cmdhf14a.c @@ -0,0 +1,200 @@ +#include +#include +#include "iso14443crc.h" +#include "data.h" +#include "proxusb.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdhf14a.h" + +static int CmdHelp(const char *Cmd); + +int CmdHF14AList(const char *Cmd) +{ + uint8_t got[1920]; + GetFromBigBuf(got, sizeof(got)); + + PrintAndLog("recorded activity:"); + PrintAndLog(" ETU :rssi: who bytes"); + PrintAndLog("---------+----+----+-----------"); + + int i = 0; + int prev = -1; + + for (;;) { + if(i >= 1900) { + break; + } + + bool isResponse; + int timestamp = *((uint32_t *)(got+i)); + if (timestamp & 0x80000000) { + timestamp &= 0x7fffffff; + isResponse = 1; + } else { + isResponse = 0; + } + + int metric = 0; + int parityBits = *((uint32_t *)(got+i+4)); + // 4 bytes of additional information... + // maximum of 32 additional parity bit information + // + // TODO: + // at each quarter bit period we can send power level (16 levels) + // or each half bit period in 256 levels. + + + int len = got[i+8]; + + if (len > 100) { + break; + } + if (i + len >= 1900) { + break; + } + + uint8_t *frame = (got+i+9); + + // Break and stick with current result if buffer was not completely full + if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; } + + char line[1000] = ""; + int j; + for (j = 0; j < len; j++) { + int oddparity = 0x01; + int k; + + for (k=0;k<8;k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); + } + + //if((parityBits >> (len - j - 1)) & 0x01) { + if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { + sprintf(line+(j*4), "%02x! ", frame[j]); + } + else { + sprintf(line+(j*4), "%02x ", frame[j]); + } + } + + char *crc; + crc = ""; + if (len > 2) { + uint8_t b1, b2; + for (j = 0; j < (len - 1); j++) { + // gives problems... search for the reason.. + /*if(frame[j] == 0xAA) { + switch(frame[j+1]) { + case 0x01: + crc = "[1] Two drops close after each other"; + break; + case 0x02: + crc = "[2] Potential SOC with a drop in second half of bitperiod"; + break; + case 0x03: + crc = "[3] Segment Z after segment X is not possible"; + break; + case 0x04: + crc = "[4] Parity bit of a fully received byte was wrong"; + break; + default: + crc = "[?] Unknown error"; + break; + } + break; + }*/ + } + + if (strlen(crc)==0) { + ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2); + if (b1 != frame[len-2] || b2 != frame[len-1]) { + crc = (isResponse & (len < 6)) ? "" : " !crc"; + } else { + crc = ""; + } + } + } else { + crc = ""; // SHORT + } + + char metricString[100]; + if (isResponse) { + sprintf(metricString, "%3d", metric); + } else { + strcpy(metricString, " "); + } + + PrintAndLog(" +%7d: %s: %s %s %s", + (prev < 0 ? 0 : (timestamp - prev)), + metricString, + (isResponse ? "TAG" : " "), line, crc); + + prev = timestamp; + i += (len + 9); + } + return 0; +} + +int CmdHF14AMifare(const char *Cmd) +{ + UsbCommand c = {CMD_READER_MIFARE, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdHF14AReader(const char *Cmd) +{ + UsbCommand c = {CMD_READER_ISO_14443a, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +// ## simulate iso14443a tag +// ## greg - added ability to specify tag UID +int CmdHF14ASim(const char *Cmd) +{ + + unsigned int hi = 0, lo = 0; + int n = 0, i = 0; + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + hi= (hi << 4) | (lo >> 28); + lo= (lo << 4) | (n & 0xf); + } + + // c.arg should be set to *Cmd or convert *Cmd to the correct format for a uid + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}}; + PrintAndLog("Emulating 14443A TAG with UID %x%16x", hi, lo); + SendCommand(&c); + return 0; +} + +int CmdHF14ASnoop(const char *Cmd) +{ + UsbCommand c = {CMD_SNOOP_ISO_14443a}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHF14AList, 0, "List ISO 14443a history"}, + {"mifare", CmdHF14AMifare, 0, "Read out sector 0 parity error messages"}, + {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"}, + {"sim", CmdHF14ASim, 0, " -- Fake ISO 14443a tag"}, + {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHF14A(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h new file mode 100644 index 00000000..2451954e --- /dev/null +++ b/client/cmdhf14a.h @@ -0,0 +1,12 @@ +#ifndef CMDHF14A_H__ +#define CMDHF14A_H__ + +int CmdHF14A(const char *Cmd); + +int CmdHF14AList(const char *Cmd); +int CmdHF14AMifare(const char *Cmd); +int CmdHF14AReader(const char *Cmd); +int CmdHF14ASim(const char *Cmd); +int CmdHF14ASnoop(const char *Cmd); + +#endif diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c new file mode 100644 index 00000000..ea5b5584 --- /dev/null +++ b/client/cmdhf14b.c @@ -0,0 +1,283 @@ +#include +#include +#include +#include +#include +#include "iso14443crc.h" +#include "proxusb.h" +#include "data.h" +#include "graph.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdhf14b.h" + +static int CmdHelp(const char *Cmd); + +int CmdHF14BDemod(const char *Cmd) +{ + int i, j, iold; + int isum, qsum; + int outOfWeakAt; + bool negateI, negateQ; + + uint8_t data[256]; + int dataLen = 0; + + // As received, the samples are pairs, correlations against I and Q + // square waves. So estimate angle of initial carrier (or just + // quadrant, actually), and then do the demod. + + // First, estimate where the tag starts modulating. + for (i = 0; i < GraphTraceLen; i += 2) { + if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) { + break; + } + } + if (i >= GraphTraceLen) { + PrintAndLog("too weak to sync"); + return 0; + } + PrintAndLog("out of weak at %d", i); + outOfWeakAt = i; + + // Now, estimate the phase in the initial modulation of the tag + isum = 0; + qsum = 0; + for (; i < (outOfWeakAt + 16); i += 2) { + isum += GraphBuffer[i + 0]; + qsum += GraphBuffer[i + 1]; + } + negateI = (isum < 0); + negateQ = (qsum < 0); + + // Turn the correlation pairs into soft decisions on the bit. + j = 0; + for (i = 0; i < GraphTraceLen / 2; i++) { + int si = GraphBuffer[j]; + int sq = GraphBuffer[j + 1]; + if (negateI) si = -si; + if (negateQ) sq = -sq; + GraphBuffer[i] = si + sq; + j += 2; + } + GraphTraceLen = i; + + i = outOfWeakAt / 2; + while (GraphBuffer[i] > 0 && i < GraphTraceLen) + i++; + if (i >= GraphTraceLen) goto demodError; + + iold = i; + while (GraphBuffer[i] < 0 && i < GraphTraceLen) + i++; + if (i >= GraphTraceLen) goto demodError; + if ((i - iold) > 23) goto demodError; + + PrintAndLog("make it to demod loop"); + + for (;;) { + iold = i; + while (GraphBuffer[i] >= 0 && i < GraphTraceLen) + i++; + if (i >= GraphTraceLen) goto demodError; + if ((i - iold) > 6) goto demodError; + + uint16_t shiftReg = 0; + if (i + 20 >= GraphTraceLen) goto demodError; + + for (j = 0; j < 10; j++) { + int soft = GraphBuffer[i] + GraphBuffer[i + 1]; + + if (abs(soft) < (abs(isum) + abs(qsum)) / 20) { + PrintAndLog("weak bit"); + } + + shiftReg >>= 1; + if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) { + shiftReg |= 0x200; + } + + i+= 2; + } + + if ((shiftReg & 0x200) && !(shiftReg & 0x001)) + { + // valid data byte, start and stop bits okay + PrintAndLog(" %02x", (shiftReg >> 1) & 0xff); + data[dataLen++] = (shiftReg >> 1) & 0xff; + if (dataLen >= sizeof(data)) { + return 0; + } + } else if (shiftReg == 0x000) { + // this is EOF + break; + } else { + goto demodError; + } + } + + uint8_t first, second; + ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second); + PrintAndLog("CRC: %02x %02x (%s)\n", first, second, + (first == data[dataLen-2] && second == data[dataLen-1]) ? + "ok" : "****FAIL****"); + + RepaintGraphWindow(); + return 0; + +demodError: + PrintAndLog("demod error"); + RepaintGraphWindow(); + return 0; +} + +int CmdHF14BList(const char *Cmd) +{ + uint8_t got[960]; + GetFromBigBuf(got, sizeof(got)); + + PrintAndLog("recorded activity:"); + PrintAndLog(" time :rssi: who bytes"); + PrintAndLog("---------+----+----+-----------"); + + int i = 0; + int prev = -1; + + for(;;) { + if(i >= 900) { + break; + } + + bool isResponse; + int timestamp = *((uint32_t *)(got+i)); + if(timestamp & 0x80000000) { + timestamp &= 0x7fffffff; + isResponse = 1; + } else { + isResponse = 0; + } + int metric = *((uint32_t *)(got+i+4)); + + int len = got[i+8]; + + if(len > 100) { + break; + } + if(i + len >= 900) { + break; + } + + uint8_t *frame = (got+i+9); + + char line[1000] = ""; + int j; + for(j = 0; j < len; j++) { + sprintf(line+(j*3), "%02x ", frame[j]); + } + + char *crc; + if(len > 2) { + uint8_t b1, b2; + ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2); + if(b1 != frame[len-2] || b2 != frame[len-1]) { + crc = "**FAIL CRC**"; + } else { + crc = ""; + } + } else { + crc = "(SHORT)"; + } + + char metricString[100]; + if(isResponse) { + sprintf(metricString, "%3d", metric); + } else { + strcpy(metricString, " "); + } + + PrintAndLog(" +%7d: %s: %s %s %s", + (prev < 0 ? 0 : timestamp - prev), + metricString, + (isResponse ? "TAG" : " "), line, crc); + + prev = timestamp; + i += (len + 9); + } + return 0; +} + +int CmdHF14BRead(const char *Cmd) +{ + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdHF14Sim(const char *Cmd) +{ + UsbCommand c={CMD_SIMULATE_TAG_ISO_14443}; + SendCommand(&c); + return 0; +} + +int CmdHFSimlisten(const char *Cmd) +{ + UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN}; + SendCommand(&c); + return 0; +} + +int CmdHF14BSnoop(const char *Cmd) +{ + UsbCommand c = {CMD_SNOOP_ISO_14443}; + SendCommand(&c); + return 0; +} + +/* New command to read the contents of a SRI512 tag + * SRI512 tags are ISO14443-B modulated memory tags, + * this command just dumps the contents of the memory + */ +int CmdSri512Read(const char *Cmd) +{ + UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +/* New command to read the contents of a SRIX4K tag + * SRIX4K tags are ISO14443-B modulated memory tags, + * this command just dumps the contents of the memory/ + */ +int CmdSrix4kRead(const char *Cmd) +{ + UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"}, + {"list", CmdHF14BList, 0, "List ISO 14443 history"}, + {"read", CmdHF14BRead, 0, "Read HF tag (ISO 14443)"}, + {"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"}, + {"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"}, + {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"}, + {"sri512read", CmdSri512Read, 0, " -- Read contents of a SRI512 tag"}, + {"srix4kread", CmdSrix4kRead, 0, " -- Read contents of a SRIX4K tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHF14B(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h new file mode 100644 index 00000000..523f079f --- /dev/null +++ b/client/cmdhf14b.h @@ -0,0 +1,15 @@ +#ifndef CMDHF14B_H__ +#define CMDHF14B_H__ + +int CmdHF14B(const char *Cmd); + +int CmdHF14BDemod(const char *Cmd); +int CmdHF14BList(const char *Cmd); +int CmdHF14BRead(const char *Cmd); +int CmdHF14Sim(const char *Cmd); +int CmdHFSimlisten(const char *Cmd); +int CmdHF14BSnoop(const char *Cmd); +int CmdSri512Read(const char *Cmd); +int CmdSrix4kRead(const char *Cmd); + +#endif diff --git a/client/cmdhf15.c b/client/cmdhf15.c new file mode 100644 index 00000000..ca3c6d93 --- /dev/null +++ b/client/cmdhf15.c @@ -0,0 +1,196 @@ +#include +#include +#include +#include +#include "proxusb.h" +#include "data.h" +#include "graph.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmdhf15.h" + +static int CmdHelp(const char *Cmd); + +static uint16_t Iso15693Crc(uint8_t *v, int n) +{ + uint32_t reg; + int i, j; + + reg = 0xffff; + for (i = 0; i < n; i++) { + reg = reg ^ ((uint32_t)v[i]); + for (j = 0; j < 8; j++) { + if (reg & 0x0001) { + reg = (reg >> 1) ^ 0x8408; + } else { + reg = (reg >> 1); + } + } + } + + return (uint16_t)~reg; +} + +int CmdHF15Demod(const char *Cmd) +{ + // The sampling rate is 106.353 ksps/s, for T = 18.8 us + + // SOF defined as + // 1) Unmodulated time of 56.64us + // 2) 24 pulses of 423.75khz + // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) + + static const int FrameSOF[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; + static const int Logic0[] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1 + }; + static const int Logic1[] = { + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; + + // EOF defined as + // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) + // 2) 24 pulses of 423.75khz + // 3) Unmodulated time of 56.64us + + static const int FrameEOF[] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + int i, j; + int max = 0, maxPos; + + int skip = 4; + + if (GraphTraceLen < 1000) return 0; + + // First, correlate for SOF + for (i = 0; i < 100; i++) { + int corr = 0; + for (j = 0; j < arraylen(FrameSOF); j += skip) { + corr += FrameSOF[j] * GraphBuffer[i + (j / skip)]; + } + if (corr > max) { + max = corr; + maxPos = i; + } + } + PrintAndLog("SOF at %d, correlation %d", maxPos, + max / (arraylen(FrameSOF) / skip)); + + i = maxPos + arraylen(FrameSOF) / skip; + int k = 0; + uint8_t outBuf[20]; + memset(outBuf, 0, sizeof(outBuf)); + uint8_t mask = 0x01; + for (;;) { + int corr0 = 0, corr1 = 0, corrEOF = 0; + for (j = 0; j < arraylen(Logic0); j += skip) { + corr0 += Logic0[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < arraylen(Logic1); j += skip) { + corr1 += Logic1[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < arraylen(FrameEOF); j += skip) { + corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)]; + } + // Even things out by the length of the target waveform. + corr0 *= 4; + corr1 *= 4; + + if (corrEOF > corr1 && corrEOF > corr0) { + PrintAndLog("EOF at %d", i); + break; + } else if (corr1 > corr0) { + i += arraylen(Logic1) / skip; + outBuf[k] |= mask; + } else { + i += arraylen(Logic0) / skip; + } + mask <<= 1; + if (mask == 0) { + k++; + mask = 0x01; + } + if ((i + (int)arraylen(FrameEOF)) >= GraphTraceLen) { + PrintAndLog("ran off end!"); + break; + } + } + if (mask != 0x01) { + PrintAndLog("error, uneven octet! (discard extra bits!)"); + PrintAndLog(" mask=%02x", mask); + } + PrintAndLog("%d octets", k); + + for (i = 0; i < k; i++) { + PrintAndLog("# %2d: %02x ", i, outBuf[i]); + } + PrintAndLog("CRC=%04x", Iso15693Crc(outBuf, k - 2)); + return 0; +} + +int CmdHF15Read(const char *Cmd) +{ + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693}; + SendCommand(&c); + return 0; +} + +int CmdHF15Reader(const char *Cmd) +{ + UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdHF15Sim(const char *Cmd) +{ + UsbCommand c = {CMD_SIMTAG_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, + {"read", CmdHF15Read, 0, "Read HF tag (ISO 15693)"}, + {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, + {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHF15(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhf15.h b/client/cmdhf15.h new file mode 100644 index 00000000..e7ca32ef --- /dev/null +++ b/client/cmdhf15.h @@ -0,0 +1,11 @@ +#ifndef CMDHF15_H__ +#define CMDHF15_H__ + +int CmdHF15(const char *Cmd); + +int CmdHF15Demod(const char *Cmd); +int CmdHF15Read(const char *Cmd); +int CmdHF15Reader(const char *Cmd); +int CmdHF15Sim(const char *Cmd); + +#endif diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c new file mode 100644 index 00000000..62ff9428 --- /dev/null +++ b/client/cmdhflegic.c @@ -0,0 +1,31 @@ +#include "proxusb.h" +#include "cmdparser.h" +#include "cmdhflegic.h" + +static int CmdHelp(const char *Cmd); + +int CmdLegicRFRead(const char *Cmd) +{ + UsbCommand c = {CMD_READER_LEGIC_RF}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"reader", CmdLegicRFRead, 0, "Start the LEGIC RF reader"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFLegic(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h new file mode 100644 index 00000000..1810322f --- /dev/null +++ b/client/cmdhflegic.h @@ -0,0 +1,8 @@ +#ifndef CMDHFLEGIC_H__ +#define CMDHFLEGIC_H__ + +int CmdHFLegic(const char *Cmd); + +int CmdLegicRFRead(const char *Cmd); + +#endif diff --git a/client/cmdhw.c b/client/cmdhw.c new file mode 100644 index 00000000..c2b58c9f --- /dev/null +++ b/client/cmdhw.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include "ui.h" +#include "proxusb.h" +#include "cmdparser.h" +#include "cmdhw.h" + +/* low-level hardware control */ + +static int CmdHelp(const char *Cmd); + +int CmdDetectReader(const char *Cmd) +{ + UsbCommand c={CMD_LISTEN_READER_FIELD}; + // 'l' means LF - 125/134 kHz + if(*Cmd == 'l') { + c.arg[0] = 1; + } else if (*Cmd == 'h') { + c.arg[0] = 2; + } else if (*Cmd != '\0') { + PrintAndLog("use 'detectreader' or 'detectreader l' or 'detectreader h'"); + return 0; + } + SendCommand(&c); + return 0; +} + +// ## FPGA Control +int CmdFPGAOff(const char *Cmd) +{ + UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF}; + SendCommand(&c); + return 0; +} + +int CmdLCD(const char *Cmd) +{ + int i, j; + + UsbCommand c={CMD_LCD}; + sscanf(Cmd, "%x %d", &i, &j); + while (j--) { + c.arg[0] = i & 0x1ff; + SendCommand(&c); + } + return 0; +} + +int CmdLCDReset(const char *Cmd) +{ + UsbCommand c = {CMD_LCD_RESET, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdReadmem(const char *Cmd) +{ + UsbCommand c = {CMD_READ_MEM, {strtol(Cmd, NULL, 0), 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdReset(const char *Cmd) +{ + UsbCommand c = {CMD_HARDWARE_RESET}; + SendCommand(&c); + return 0; +} + +/* + * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below + * 600kHz. + */ +int CmdSetDivisor(const char *Cmd) +{ + UsbCommand c = {CMD_SET_LF_DIVISOR, {strtol(Cmd, NULL, 0), 0, 0}}; + if (c.arg[0] < 0 || c.arg[0] > 255) { + PrintAndLog("divisor must be between 19 and 255"); + } else { + SendCommand(&c); + PrintAndLog("Divisor set, expected freq=%dHz", 12000000 / (c.arg[0]+1)); + } + return 0; +} + +int CmdSetMux(const char *Cmd) +{ + UsbCommand c={CMD_SET_ADC_MUX}; + if (strcmp(Cmd, "lopkd") == 0) { + c.arg[0] = 0; + } else if (strcmp(Cmd, "loraw") == 0) { + c.arg[0] = 1; + } else if (strcmp(Cmd, "hipkd") == 0) { + c.arg[0] = 2; + } else if (strcmp(Cmd, "hiraw") == 0) { + c.arg[0] = 3; + } + SendCommand(&c); + return 0; +} + +int CmdTune(const char *Cmd) +{ + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING}; + SendCommand(&c); + return 0; +} + +int CmdVersion(const char *Cmd) +{ + UsbCommand c = {CMD_VERSION}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHW(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhw.h b/client/cmdhw.h new file mode 100644 index 00000000..3a85bc73 --- /dev/null +++ b/client/cmdhw.h @@ -0,0 +1,17 @@ +#ifndef CMDHW_H__ +#define CMDHW_H__ + +int CmdHW(const char *Cmd); + +int CmdDetectReader(const char *Cmd); +int CmdFPGAOff(const char *Cmd); +int CmdLCD(const char *Cmd); +int CmdLCDReset(const char *Cmd); +int CmdReadmem(const char *Cmd); +int CmdReset(const char *Cmd); +int CmdSetDivisor(const char *Cmd); +int CmdSetMux(const char *Cmd); +int CmdTune(const char *Cmd); +int CmdVersion(const char *Cmd); + +#endif diff --git a/client/cmdlf.c b/client/cmdlf.c new file mode 100644 index 00000000..e82e48ae --- /dev/null +++ b/client/cmdlf.c @@ -0,0 +1,453 @@ +#include +#include +#include "proxusb.h" +#include "data.h" +#include "graph.h" +#include "ui.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "cmdlfhid.h" +#include "cmdlfti.h" +#include "cmdlfem4x.h" + +static int CmdHelp(const char *Cmd); + +/* send a command before reading */ +int CmdLFCommandRead(const char *Cmd) +{ + static char dummy[3]; + + dummy[0]= ' '; + + UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; + sscanf(Cmd, "%i %i %i %s %s", &c.arg[0], &c.arg[1], &c.arg[2], (char *) &c.d.asBytes,(char *) &dummy+1); + // in case they specified 'h' + strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); + SendCommand(&c); + return 0; +} + +int CmdFlexdemod(const char *Cmd) +{ + int i; + for (i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] < 0) { + GraphBuffer[i] = -1; + } else { + GraphBuffer[i] = 1; + } + } + +#define LONG_WAIT 100 + int start; + for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) { + int first = GraphBuffer[start]; + for (i = start; i < start + LONG_WAIT; i++) { + if (GraphBuffer[i] != first) { + break; + } + } + if (i == (start + LONG_WAIT)) { + break; + } + } + if (start == GraphTraceLen - LONG_WAIT) { + PrintAndLog("nothing to wait for"); + return 0; + } + + GraphBuffer[start] = 2; + GraphBuffer[start+1] = -2; + + uint8_t bits[64]; + + int bit; + i = start; + for (bit = 0; bit < 64; bit++) { + int j; + int sum = 0; + for (j = 0; j < 16; j++) { + sum += GraphBuffer[i++]; + } + if (sum > 0) { + bits[bit] = 1; + } else { + bits[bit] = 0; + } + PrintAndLog("bit %d sum %d", bit, sum); + } + + for (bit = 0; bit < 64; bit++) { + int j; + int sum = 0; + for (j = 0; j < 16; j++) { + sum += GraphBuffer[i++]; + } + if (sum > 0 && bits[bit] != 1) { + PrintAndLog("oops1 at %d", bit); + } + if (sum < 0 && bits[bit] != 0) { + PrintAndLog("oops2 at %d", bit); + } + } + + GraphTraceLen = 32*64; + i = 0; + int phase = 0; + for (bit = 0; bit < 64; bit++) { + if (bits[bit] == 0) { + phase = 0; + } else { + phase = 1; + } + int j; + for (j = 0; j < 32; j++) { + GraphBuffer[i++] = phase; + phase = !phase; + } + } + + RepaintGraphWindow(); + return 0; +} + +int CmdIndalaDemod(const char *Cmd) +{ + // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID + + int state = -1; + int count = 0; + int i, j; + // worst case with GraphTraceLen=64000 is < 4096 + // under normal conditions it's < 2048 + uint8_t rawbits[4096]; + int rawbit = 0; + int worst = 0, worstPos = 0; + PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); + for (i = 0; i < GraphTraceLen-1; i += 2) { + count += 1; + if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { + if (state == 0) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 0; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 1; + count = 0; + } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { + if (state == 1) { + for (j = 0; j < count - 8; j += 16) { + rawbits[rawbit++] = 1; + } + if ((abs(count - j)) > worst) { + worst = abs(count - j); + worstPos = i; + } + } + state = 0; + count = 0; + } + } + PrintAndLog("Recovered %d raw bits", rawbit); + PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); + + // Finding the start of a UID + int uidlen, long_wait; + if (strcmp(Cmd, "224") == 0) { + uidlen = 224; + long_wait = 30; + } else { + uidlen = 64; + long_wait = 29; + } + int start; + int first = 0; + for (start = 0; start <= rawbit - uidlen; start++) { + first = rawbits[start]; + for (i = start; i < start + long_wait; i++) { + if (rawbits[i] != first) { + break; + } + } + if (i == (start + long_wait)) { + break; + } + } + if (start == rawbit - uidlen + 1) { + PrintAndLog("nothing to wait for"); + return 0; + } + + // Inverting signal if needed + if (first == 1) { + for (i = start; i < rawbit; i++) { + rawbits[i] = !rawbits[i]; + } + } + + // Dumping UID + uint8_t bits[224]; + char showbits[225]; + showbits[uidlen]='\0'; + int bit; + i = start; + int times = 0; + if (uidlen > rawbit) { + PrintAndLog("Warning: not enough raw bits to get a full UID"); + for (bit = 0; bit < rawbit; bit++) { + bits[bit] = rawbits[i++]; + // As we cannot know the parity, let's use "." and "/" + showbits[bit] = '.' + bits[bit]; + } + showbits[bit+1]='\0'; + PrintAndLog("Partial UID=%s", showbits); + return 0; + } else { + for (bit = 0; bit < uidlen; bit++) { + bits[bit] = rawbits[i++]; + showbits[bit] = '0' + bits[bit]; + } + times = 1; + } + PrintAndLog("UID=%s", showbits); + + // Checking UID against next occurences + for (; i + uidlen <= rawbit;) { + int failed = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] != rawbits[i++]) { + failed = 1; + break; + } + } + if (failed == 1) { + break; + } + times += 1; + } + PrintAndLog("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen); + + // Remodulating for tag cloning + GraphTraceLen = 32*uidlen; + i = 0; + int phase = 0; + for (bit = 0; bit < uidlen; bit++) { + if (bits[bit] == 0) { + phase = 0; + } else { + phase = 1; + } + int j; + for (j = 0; j < 32; j++) { + GraphBuffer[i++] = phase; + phase = !phase; + } + } + + RepaintGraphWindow(); + return 0; +} + +int CmdLFRead(const char *Cmd) +{ + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; + // 'h' means higher-low-frequency, 134 kHz + if(*Cmd == 'h') { + c.arg[0] = 1; + } else if (*Cmd == '\0') { + c.arg[0] = 0; + } else { + PrintAndLog("use 'read' or 'read h'"); + return 0; + } + SendCommand(&c); + return 0; +} + +static void ChkBitstream(const char *str) +{ + int i; + + /* convert to bitstream if necessary */ + for (i = 0; i < (int)(GraphTraceLen / 2); i++) + { + if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) + { + CmdBitstream(str); + break; + } + } +} + +int CmdLFSim(const char *Cmd) +{ + int i; + static int gap; + + sscanf(Cmd, "%i", &gap); + + /* convert to bitstream if necessary */ + ChkBitstream(Cmd); + + PrintAndLog("Sending data, please wait..."); + for (i = 0; i < GraphTraceLen; i += 48) { + UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}}; + int j; + for (j = 0; j < 48; j++) { + c.d.asBytes[j] = GraphBuffer[i+j]; + } + SendCommand(&c); + WaitForResponse(CMD_ACK); + } + + PrintAndLog("Starting simulator..."); + UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}}; + SendCommand(&c); + return 0; +} + +int CmdLFSimBidir(const char *Cmd) +{ + /* Set ADC to twice the carrier for a slight supersampling */ + UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}}; + SendCommand(&c); + return 0; +} + +/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */ +int CmdLFSimManchester(const char *Cmd) +{ + static int clock, gap; + static char data[1024], gapstring[8]; + + /* get settings/bits */ + sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap); + + /* clear our graph */ + ClearGraph(0); + + /* fill it with our bitstream */ + for (int i = 0; i < strlen(data) ; ++i) + AppendGraph(0, clock, data[i]- '0'); + + /* modulate */ + CmdManchesterMod(""); + + /* show what we've done */ + RepaintGraphWindow(); + + /* simulate */ + sprintf(&gapstring[0], "%i", gap); + CmdLFSim(gapstring); + return 0; +} + +int CmdVchDemod(const char *Cmd) +{ + // Is this the entire sync pattern, or does this also include some + // data bits that happen to be the same everywhere? That would be + // lovely to know. + static const int SyncPattern[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + // So first, we correlate for the sync pattern, and mark that. + int bestCorrel = 0, bestPos = 0; + int i; + // It does us no good to find the sync pattern, with fewer than + // 2048 samples after it... + for (i = 0; i < (GraphTraceLen-2048); i++) { + int sum = 0; + int j; + for (j = 0; j < arraylen(SyncPattern); j++) { + sum += GraphBuffer[i+j]*SyncPattern[j]; + } + if (sum > bestCorrel) { + bestCorrel = sum; + bestPos = i; + } + } + PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel); + + char bits[257]; + bits[256] = '\0'; + + int worst = INT_MAX; + int worstPos; + + for (i = 0; i < 2048; i += 8) { + int sum = 0; + int j; + for (j = 0; j < 8; j++) { + sum += GraphBuffer[bestPos+i+j]; + } + if (sum < 0) { + bits[i/8] = '.'; + } else { + bits[i/8] = '1'; + } + if(abs(sum) < worst) { + worst = abs(sum); + worstPos = i; + } + } + PrintAndLog("bits:"); + PrintAndLog("%s", bits); + PrintAndLog("worst metric: %d at pos %d", worst, worstPos); + + if (strcmp(Cmd, "clone")==0) { + GraphTraceLen = 0; + char *s; + for(s = bits; *s; s++) { + int j; + for(j = 0; j < 16; j++) { + GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0; + } + } + RepaintGraphWindow(); + } + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, + {"em4x", CmdLFEM4X, 1, "EM4X RFIDs"}, + {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, + {"hid", CmdLFHID, 1, "HID RFIDs"}, + {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, + {"read", CmdLFRead, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"}, + {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, + {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, + {"simman", CmdLFSimManchester, 0, " [GAP] Simulate arbitrary Manchester LF tag"}, + {"ti", CmdLFTI, 1, "TI RFIDs"}, + {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLF(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlf.h b/client/cmdlf.h new file mode 100644 index 00000000..4055cf91 --- /dev/null +++ b/client/cmdlf.h @@ -0,0 +1,15 @@ +#ifndef CMDLF_H__ +#define CMDLF_H__ + +int CmdLF(const char *Cmd); + +int CmdLFCommandRead(const char *Cmd); +int CmdFlexdemod(const char *Cmd); +int CmdIndalaDemod(const char *Cmd); +int CmdLFRead(const char *Cmd); +int CmdLFSim(const char *Cmd); +int CmdLFSimBidir(const char *Cmd); +int CmdLFSimManchester(const char *Cmd); +int CmdVchDemod(const char *Cmd); + +#endif diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c new file mode 100644 index 00000000..52d407ab --- /dev/null +++ b/client/cmdlfem4x.c @@ -0,0 +1,415 @@ +#include +#include "proxusb.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "cmdlfem4x.h" + +static int CmdHelp(const char *Cmd); + +/* Read the ID of an EM410x tag. + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +int CmdEM410xRead(const char *Cmd) +{ + int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low; + int parity[4]; + char id[11]; + int retested = 0; + int BitStream[MAX_GRAPH_TRACE_LEN]; + high = low = 0; + + /* Detect high and lows and clock */ + for (i = 0; i < GraphTraceLen; i++) + { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + + /* get clock */ + clock = GetClock(Cmd, high, 0); + + /* parity for our 4 columns */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + header = rows = 0; + + /* manchester demodulate */ + bit = bit2idx = 0; + for (i = 0; i < (int)(GraphTraceLen / clock); i++) + { + hithigh = 0; + hitlow = 0; + first = 1; + + /* Find out if we hit both high and low peaks */ + for (j = 0; j < clock; j++) + { + if (GraphBuffer[(i * clock) + j] == high) + hithigh = 1; + else if (GraphBuffer[(i * clock) + j] == low) + hitlow = 1; + + /* it doesn't count if it's the first part of our read + because it's really just trailing from the last sequence */ + if (first && (hithigh || hitlow)) + hithigh = hitlow = 0; + else + first = 0; + + if (hithigh && hitlow) + break; + } + + /* If we didn't hit both high and low peaks, we had a bit transition */ + if (!hithigh || !hitlow) + bit ^= 1; + + BitStream[bit2idx++] = bit; + } + +retest: + /* We go till 5 before the graph ends because we'll get that far below */ + for (i = 1; i < bit2idx - 5; i++) + { + /* Step 2: We have our header but need our tag ID */ + if (header == 9 && rows < 10) + { + /* Confirm parity is correct */ + if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4]) + { + /* Read another byte! */ + sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3])); + rows++; + + /* Keep parity info */ + parity[0] ^= BitStream[i]; + parity[1] ^= BitStream[i+1]; + parity[2] ^= BitStream[i+2]; + parity[3] ^= BitStream[i+3]; + + /* Move 4 bits ahead */ + i += 4; + } + + /* Damn, something wrong! reset */ + else + { + PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i); + + /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ + i -= 9 + (5 * rows) - 5; + + rows = header = 0; + } + } + + /* Step 3: Got our 40 bits! confirm column parity */ + else if (rows == 10) + { + /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ + if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] && + BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] && + BitStream[i+4] == 0) + { + /* Sweet! */ + PrintAndLog("EM410x Tag ID: %s", id); + + /* Stop any loops */ + return 1; + } + + /* Crap! Incorrect parity or no stop bit, start all over */ + else + { + rows = header = 0; + + /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ + i -= 59; + } + } + + /* Step 1: get our header */ + else if (header < 9) + { + /* Need 9 consecutive 1's */ + if (BitStream[i] == 1) + header++; + + /* We don't have a header, not enough consecutive 1 bits */ + else + header = 0; + } + } + + /* if we've already retested after flipping bits, return */ + if (retested++) + return 0; + + /* if this didn't work, try flipping bits */ + for (i = 0; i < bit2idx; i++) + BitStream[i] ^= 1; + + goto retest; +} + +/* emulate an EM410X tag + * Format: + * 1111 1111 1 <-- standard non-repeatable header + * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID + * .... + * CCCC <-- each bit here is parity for the 10 bits above in corresponding column + * 0 <-- stop bit, end of tag + */ +int CmdEM410xSim(const char *Cmd) +{ + int i, n, j, h, binary[4], parity[4]; + + /* clock is 64 in EM410x tags */ + int clock = 64; + + /* clear our graph */ + ClearGraph(0); + + /* write it out a few times */ + for (h = 0; h < 4; h++) + { + /* write 9 start bits */ + for (i = 0; i < 9; i++) + AppendGraph(0, clock, 1); + + /* for each hex char */ + parity[0] = parity[1] = parity[2] = parity[3] = 0; + for (i = 0; i < 10; i++) + { + /* read each hex char */ + sscanf(&Cmd[i], "%1x", &n); + for (j = 3; j >= 0; j--, n/= 2) + binary[j] = n % 2; + + /* append each bit */ + AppendGraph(0, clock, binary[0]); + AppendGraph(0, clock, binary[1]); + AppendGraph(0, clock, binary[2]); + AppendGraph(0, clock, binary[3]); + + /* append parity bit */ + AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + + /* keep track of column parity */ + parity[0] ^= binary[0]; + parity[1] ^= binary[1]; + parity[2] ^= binary[2]; + parity[3] ^= binary[3]; + } + + /* parity columns */ + AppendGraph(0, clock, parity[0]); + AppendGraph(0, clock, parity[1]); + AppendGraph(0, clock, parity[2]); + AppendGraph(0, clock, parity[3]); + + /* stop bit */ + AppendGraph(0, clock, 0); + } + + /* modulate that biatch */ + CmdManchesterMod(""); + + /* booyah! */ + RepaintGraphWindow(); + + CmdLFSim(""); + return 0; +} + +/* Function is equivalent of loread + losamples + em410xread + * looped until an EM410x tag is detected */ +int CmdEM410xWatch(const char *Cmd) +{ + char *zero = ""; + char *twok = "2000"; + + int stop = 0; + do + { + CmdLFRead(zero); + CmdLFSamples(twok); + stop = CmdEM410xRead(zero); + } while (!stop); + return 0; +} + +/* Read the transmitted data of an EM4x50 tag + * Format: + * + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity + * CCCCCCCC <- column parity bits + * 0 <- stop bit + * LW <- Listen Window + * + * This pattern repeats for every block of data being transmitted. + * Transmission starts with two Listen Windows (LW - a modulated + * pattern of 320 cycles each (32/32/128/64/64)). + * + * Note that this data may or may not be the UID. It is whatever data + * is stored in the blocks defined in the control word First and Last + * Word Read values. UID is stored in block 32. + */ +int CmdEM4x50Read(const char *Cmd) +{ + int i, j, startblock, clock, skip, block, start, end, low, high; + bool complete= false; + int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; + char tmp[6]; + + high= low= 0; + clock= 64; + + /* first get high and low values */ + for (i = 0; i < GraphTraceLen; i++) + { + if (GraphBuffer[i] > high) + high = GraphBuffer[i]; + else if (GraphBuffer[i] < low) + low = GraphBuffer[i]; + } + + /* populate a buffer with pulse lengths */ + i= 0; + j= 0; + while (i < GraphTraceLen) + { + // measure from low to low + while ((GraphBuffer[i] > low) && (i low) && (i(MAX_GRAPH_TRACE_LEN/64)) { + break; + } + tmpbuff[j++]= i - start; + } + + /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ + start= -1; + skip= 0; + for (i= 0; i < j - 4 ; ++i) + { + skip += tmpbuff[i]; + if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) + if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) + if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) + if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) + { + start= i + 3; + break; + } + } + startblock= i + 3; + + /* skip over the remainder of the LW */ + skip += tmpbuff[i+1]+tmpbuff[i+2]; + while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low) + ++skip; + skip += 8; + + /* now do it again to find the end */ + end= start; + for (i += 3; i < j - 4 ; ++i) + { + end += tmpbuff[i]; + if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) + if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) + if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) + if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) + { + complete= true; + break; + } + } + + if (start >= 0) + PrintAndLog("Found data at sample: %i",skip); + else + { + PrintAndLog("No data found!"); + PrintAndLog("Try again with more samples."); + return 0; + } + + if (!complete) + { + PrintAndLog("*** Warning!"); + PrintAndLog("Partial data - no end found!"); + PrintAndLog("Try again with more samples."); + } + + /* get rid of leading crap */ + sprintf(tmp,"%i",skip); + CmdLtrim(tmp); + + /* now work through remaining buffer printing out data blocks */ + block= 0; + i= startblock; + while (block < 6) + { + PrintAndLog("Block %i:", block); + // mandemod routine needs to be split so we can call it for data + // just print for now for debugging + CmdManchesterDemod("i 64"); + skip= 0; + /* look for LW before start of next block */ + for ( ; i < j - 4 ; ++i) + { + skip += tmpbuff[i]; + if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) + if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) + break; + } + while (GraphBuffer[skip] > low) + ++skip; + skip += 8; + sprintf(tmp,"%i",skip); + CmdLtrim(tmp); + start += skip; + block++; + } + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, + {"em410xsim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, + {"em410xwatch", CmdEM410xWatch, 0, "Watches for EM410x tags"}, + {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFEM4X(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h new file mode 100644 index 00000000..53f3fe81 --- /dev/null +++ b/client/cmdlfem4x.h @@ -0,0 +1,11 @@ +#ifndef CMDLFEM4X_H__ +#define CMDLFEM4X_H__ + +int CmdLFEM4X(const char *Cmd); + +int CmdEM410xRead(const char *Cmd); +int CmdEM410xSim(const char *Cmd); +int CmdEM410xWatch(const char *Cmd); +int CmdEM4x50Read(const char *Cmd); + +#endif diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c new file mode 100644 index 00000000..744138c0 --- /dev/null +++ b/client/cmdlfhid.c @@ -0,0 +1,72 @@ +#include +#include "proxusb.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmdlfhid.h" + +static int CmdHelp(const char *Cmd); + +int CmdHIDDemod(const char *Cmd) +{ + if (GraphTraceLen < 4800) { + PrintAndLog("too short; need at least 4800 samples"); + return 0; + } + + GraphTraceLen = 4800; + for (int i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] < 0) { + GraphBuffer[i] = 0; + } else { + GraphBuffer[i] = 1; + } + } + RepaintGraphWindow(); + return 0; +} + +int CmdHIDDemodFSK(const char *Cmd) +{ + UsbCommand c={CMD_HID_DEMOD_FSK}; + SendCommand(&c); + return 0; +} + +int CmdHIDSim(const char *Cmd) +{ + unsigned int hi = 0, lo = 0; + int n = 0, i = 0; + + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + hi = (hi << 4) | (lo >> 28); + lo = (lo << 4) | (n & 0xf); + } + + PrintAndLog("Emulating tag with ID %x%16x", hi, lo); + + UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}}; + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"}, + {"fskdemod", CmdHIDDemodFSK, 0, "Realtime HID FSK demodulator"}, + {"sim", CmdHIDSim, 0, " -- HID tag simulator"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFHID(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h new file mode 100644 index 00000000..7747fd28 --- /dev/null +++ b/client/cmdlfhid.h @@ -0,0 +1,10 @@ +#ifndef CMDLFHID_H__ +#define CMDLFHID_H__ + +int CmdLFHID(const char *Cmd); + +int CmdHIDDemod(const char *Cmd); +int CmdHIDDemodFSK(const char *Cmd); +int CmdHIDSim(const char *Cmd); + +#endif diff --git a/client/cmdlfti.c b/client/cmdlfti.c new file mode 100644 index 00000000..a0e2bb84 --- /dev/null +++ b/client/cmdlfti.c @@ -0,0 +1,293 @@ +#include +#include "crc16.h" +#include "proxusb.h" +#include "data.h" +#include "ui.h" +#include "graph.h" +#include "cmdparser.h" +#include "cmdlfti.h" + +static int CmdHelp(const char *Cmd); + +int CmdTIDemod(const char *Cmd) +{ + /* MATLAB as follows: + f_s = 2000000; % sampling frequency + f_l = 123200; % low FSK tone + f_h = 134200; % high FSK tone + + T_l = 119e-6; % low bit duration + T_h = 130e-6; % high bit duration + + l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); + h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); + + l = sign(sin(cumsum(l))); + h = sign(sin(cumsum(h))); + */ + + // 2M*16/134.2k = 238 + static const int LowTone[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 + }; + // 2M*16/123.2k = 260 + static const int HighTone[] = { + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + int lowLen = sizeof(LowTone)/sizeof(int); + int highLen = sizeof(HighTone)/sizeof(int); + int convLen = (highLen>lowLen)?highLen:lowLen; + uint16_t crc; + int i, j, TagType; + int lowSum = 0, highSum = 0;; + int lowTot = 0, highTot = 0; + + for (i = 0; i < GraphTraceLen - convLen; i++) { + lowSum = 0; + highSum = 0;; + + for (j = 0; j < lowLen; j++) { + lowSum += LowTone[j]*GraphBuffer[i+j]; + } + for (j = 0; j < highLen; j++) { + highSum += HighTone[j]*GraphBuffer[i+j]; + } + lowSum = abs((100*lowSum) / lowLen); + highSum = abs((100*highSum) / highLen); + lowSum = (lowSum<0)?-lowSum:lowSum; + highSum = (highSum<0)?-highSum:highSum; + + GraphBuffer[i] = (highSum << 16) | lowSum; + } + + for (i = 0; i < GraphTraceLen - convLen - 16; i++) { + lowTot = 0; + highTot = 0; + // 16 and 15 are f_s divided by f_l and f_h, rounded + for (j = 0; j < 16; j++) { + lowTot += (GraphBuffer[i+j] & 0xffff); + } + for (j = 0; j < 15; j++) { + highTot += (GraphBuffer[i+j] >> 16); + } + GraphBuffer[i] = lowTot - highTot; + } + + GraphTraceLen -= (convLen + 16); + + RepaintGraphWindow(); + + // TI tag data format is 16 prebits, 8 start bits, 64 data bits, + // 16 crc CCITT bits, 8 stop bits, 15 end bits + + // the 16 prebits are always low + // the 8 start and stop bits of a tag must match + // the start/stop prebits of a ro tag are 01111110 + // the start/stop prebits of a rw tag are 11111110 + // the 15 end bits of a ro tag are all low + // the 15 end bits of a rw tag match bits 15-1 of the data bits + + // Okay, so now we have unsliced soft decisions; + // find bit-sync, and then get some bits. + // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags) + int max = 0, maxPos = 0; + for (i = 0; i < 6000; i++) { + int j; + int dec = 0; + // searching 17 consecutive lows + for (j = 0; j < 17*lowLen; j++) { + dec -= GraphBuffer[i+j]; + } + // searching 7 consecutive highs + for (; j < 17*lowLen + 6*highLen; j++) { + dec += GraphBuffer[i+j]; + } + if (dec > max) { + max = dec; + maxPos = i; + } + } + + // place a marker in the buffer to visually aid location + // of the start of sync + GraphBuffer[maxPos] = 800; + GraphBuffer[maxPos+1] = -800; + + // advance pointer to start of actual data stream (after 16 pre and 8 start bits) + maxPos += 17*lowLen; + maxPos += 6*highLen; + + // place a marker in the buffer to visually aid location + // of the end of sync + GraphBuffer[maxPos] = 800; + GraphBuffer[maxPos+1] = -800; + + PrintAndLog("actual data bits start at sample %d", maxPos); + + PrintAndLog("length %d/%d", highLen, lowLen); + + uint8_t bits[1+64+16+8+16]; + bits[sizeof(bits)-1] = '\0'; + + uint32_t shift3 = 0x7e000000, shift2 = 0, shift1 = 0, shift0 = 0; + + for (i = 0; i < arraylen(bits)-1; i++) { + int high = 0; + int low = 0; + int j; + for (j = 0; j < lowLen; j++) { + low -= GraphBuffer[maxPos+j]; + } + for (j = 0; j < highLen; j++) { + high += GraphBuffer[maxPos+j]; + } + + if (high > low) { + bits[i] = '1'; + maxPos += highLen; + // bitstream arrives lsb first so shift right + shift3 |= (1<<31); + } else { + bits[i] = '.'; + maxPos += lowLen; + } + + // 128 bit right shift register + shift0 = (shift0>>1) | (shift1 << 31); + shift1 = (shift1>>1) | (shift2 << 31); + shift2 = (shift2>>1) | (shift3 << 31); + shift3 >>= 1; + + // place a marker in the buffer between bits to visually aid location + GraphBuffer[maxPos] = 800; + GraphBuffer[maxPos+1] = -800; + } + PrintAndLog("Info: raw tag bits = %s", bits); + + TagType = (shift3>>8)&0xff; + if ( TagType != ((shift0>>16)&0xff) ) { + PrintAndLog("Error: start and stop bits do not match!"); + return 0; + } + else if (TagType == 0x7e) { + PrintAndLog("Info: Readonly TI tag detected."); + return 0; + } + else if (TagType == 0xfe) { + PrintAndLog("Info: Rewriteable TI tag detected."); + + // put 64 bit data into shift1 and shift0 + shift0 = (shift0>>24) | (shift1 << 8); + shift1 = (shift1>>24) | (shift2 << 8); + + // align 16 bit crc into lower half of shift2 + shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff; + + // align 16 bit "end bits" or "ident" into lower half of shift3 + shift3 >>= 16; + + // only 15 bits compare, last bit of ident is not valid + if ( (shift3^shift0)&0x7fff ) { + PrintAndLog("Error: Ident mismatch!"); + } + // WARNING the order of the bytes in which we calc crc below needs checking + // i'm 99% sure the crc algorithm is correct, but it may need to eat the + // bytes in reverse or something + // calculate CRC + crc=0; + crc = update_crc16(crc, (shift0)&0xff); + crc = update_crc16(crc, (shift0>>8)&0xff); + crc = update_crc16(crc, (shift0>>16)&0xff); + crc = update_crc16(crc, (shift0>>24)&0xff); + crc = update_crc16(crc, (shift1)&0xff); + crc = update_crc16(crc, (shift1>>8)&0xff); + crc = update_crc16(crc, (shift1>>16)&0xff); + crc = update_crc16(crc, (shift1>>24)&0xff); + PrintAndLog("Info: Tag data = %08X%08X", shift1, shift0); + if (crc != (shift2&0xffff)) { + PrintAndLog("Error: CRC mismatch, calculated %04X, got ^04X", crc, shift2&0xffff); + } else { + PrintAndLog("Info: CRC %04X is good", crc); + } + } + else { + PrintAndLog("Unknown tag type."); + return 0; + } + return 0; +} + +// read a TI tag and return its ID +int CmdTIRead(const char *Cmd) +{ + UsbCommand c = {CMD_READ_TI_TYPE}; + SendCommand(&c); + return 0; +} + +// write new data to a r/w TI tag +int CmdTIWrite(const char *Cmd) +{ + UsbCommand c = {CMD_WRITE_TI_TYPE}; + int res = 0; + + res = sscanf(Cmd, "0x%x 0x%x 0x%x ", &c.arg[0], &c.arg[1], &c.arg[2]); + if (res == 2) c.arg[2]=0; + if (res < 2) + PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third"); + else + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag"}, + {"read", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"}, + {"write", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFTI(const char *Cmd) +{ + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfti.h b/client/cmdlfti.h new file mode 100644 index 00000000..9554bb1a --- /dev/null +++ b/client/cmdlfti.h @@ -0,0 +1,10 @@ +#ifndef CMDLFTI_H__ +#define CMDLFTI_H__ + +int CmdLFTI(const char *Cmd); + +int CmdTIDemod(const char *Cmd); +int CmdTIRead(const char *Cmd); +int CmdTIWrite(const char *Cmd); + +#endif diff --git a/client/cmdmain.c b/client/cmdmain.c new file mode 100644 index 00000000..322e5806 --- /dev/null +++ b/client/cmdmain.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include "cmdparser.h" +#include "data.h" +#include "usb_cmd.h" +#include "ui.h" +#include "cmdhf.h" +#include "cmddata.h" +#include "cmdhw.h" +#include "cmdlf.h" +#include "cmdmain.h" + +unsigned int current_command = CMD_UNKNOWN; +unsigned int received_command = CMD_UNKNOWN; + +static int CmdHelp(const char *Cmd); +static int CmdQuit(const char *Cmd); + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"data", CmdData, 1, "Plot window / data buffer manipulation"}, + {"exit", CmdQuit, 1, "Exit program"}, + {"hf", CmdHF, 1, "HF commands"}, + {"hw", CmdHW, 1, "Hardware commands"}, + {"lf", CmdLF, 1, "LF commands"}, + {"quit", CmdQuit, 1, "Quit program"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} + +int CmdQuit(const char *Cmd) +{ + exit(0); + return 0; +} + +void WaitForResponse(uint32_t response_type) +{ + while (received_command != response_type) { +#ifdef WIN32 + UsbCommand c; + if (ReceiveCommandPoll(&c)) + UsbCommandReceived(&c); + Sleep(0); +#else + usleep(10000); // XXX ugh +#endif + } + received_command = CMD_UNKNOWN; +} + +//----------------------------------------------------------------------------- +// Entry point into our code: called whenever the user types a command and +// then presses Enter, which the full command line that they typed. +//----------------------------------------------------------------------------- +void CommandReceived(char *Cmd) +{ + CmdsParse(CommandTable, Cmd); +} + +//----------------------------------------------------------------------------- +// Entry point into our code: called whenever we received a packet over USB +// that we weren't necessarily expecting, for example a debug print. +//----------------------------------------------------------------------------- +void UsbCommandReceived(UsbCommand *UC) +{ + // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command); + /* If we recognize a response, return to avoid further processing */ + switch(UC->cmd) { + case CMD_DEBUG_PRINT_STRING: { + char s[100]; + if(UC->arg[0] > 70 || UC->arg[0] < 0) { + UC->arg[0] = 0; + } + memcpy(s, UC->d.asBytes, UC->arg[0]); + s[UC->arg[0]] = '\0'; + PrintAndLog("#db# %s", s); + return; + } + + case CMD_DEBUG_PRINT_INTEGERS: + PrintAndLog("#db# %08x, %08x, %08x\r\n", UC->arg[0], UC->arg[1], UC->arg[2]); + return; + + case CMD_MEASURED_ANTENNA_TUNING: { + int peakv, peakf; + int vLf125, vLf134, vHf; + vLf125 = UC->arg[0] & 0xffff; + vLf134 = UC->arg[0] >> 16; + vHf = UC->arg[1] & 0xffff;; + peakf = UC->arg[2] & 0xffff; + peakv = UC->arg[2] >> 16; + PrintAndLog(""); + PrintAndLog(""); + PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); + PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); + PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); + PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); + if (peakv<2000) + PrintAndLog("# Your LF antenna is unusable."); + else if (peakv<10000) + PrintAndLog("# Your LF antenna is marginal."); + if (vHf<2000) + PrintAndLog("# Your HF antenna is unusable."); + else if (vHf<5000) + PrintAndLog("# Your HF antenna is marginal."); + return; + } + default: + break; + } + /* Maybe it's a response: */ + switch(current_command) { + case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: + if (UC->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) goto unexpected_response; + int i; + for(i=0; i<48; i++) sample_buf[i] = UC->d.asBytes[i]; + received_command = UC->cmd; + return; + case CMD_DOWNLOADED_SIM_SAMPLES_125K: + if (UC->cmd != CMD_ACK) goto unexpected_response; + // got ACK + received_command = UC->cmd; + return; + default: + unexpected_response: + PrintAndLog("unrecognized command %08x\n", UC->cmd); + break; + } +} \ No newline at end of file diff --git a/client/cmdmain.h b/client/cmdmain.h new file mode 100644 index 00000000..5a34d178 --- /dev/null +++ b/client/cmdmain.h @@ -0,0 +1,10 @@ +#ifndef CMDMAIN_H__ +#define CMDMAIN_H__ + +#include "usb_cmd.h" + +void UsbCommandReceived(UsbCommand *UC); +void CommandReceived(char *Cmd); +void WaitForResponse(uint32_t response_type); + +#endif diff --git a/client/cmdparser.c b/client/cmdparser.c new file mode 100644 index 00000000..b91f2c9e --- /dev/null +++ b/client/cmdparser.c @@ -0,0 +1,32 @@ +#include +#include +#include "ui.h" +#include "cmdparser.h" + +void CmdsHelp(const command_t Commands[]) +{ + if (Commands[0].Name == NULL) + return; + int i = 0; + while (Commands[i].Name) + { + if (!offline || Commands[i].Offline) + PrintAndLog("%-16s %s", Commands[i].Name, Commands[i].Help); + ++i; + } +} + +void CmdsParse(const command_t Commands[], const char *Cmd) +{ + char cmd_name[32]; + int len = 0; + memset(cmd_name, 0, 32); + sscanf(Cmd, "%31s%n", cmd_name, &len); + int i = 0; + while (Commands[i].Name && strcmp(Commands[i].Name, cmd_name)) + ++i; + if (Commands[i].Name) + Commands[i].Parse(Cmd + len); + else + PrintAndLog("Command not found"); +} diff --git a/client/cmdparser.h b/client/cmdparser.h new file mode 100644 index 00000000..706ee988 --- /dev/null +++ b/client/cmdparser.h @@ -0,0 +1,19 @@ +#ifndef CMDPARSER_H__ +#define CMDPARSER_H__ + +typedef struct command_s +{ + const char * Name; + int (*Parse)(const char *Cmd); + int Offline; + const char * Help; +} command_t; + +// command_t array are expected to be NULL terminated + +// Print help for each command in the command array +void CmdsHelp(const command_t Commands[]); +// Parse a command line +void CmdsParse(const command_t Commands[], const char *Cmd); + +#endif \ No newline at end of file diff --git a/client/command.c b/client/command.c deleted file mode 100644 index 0d954258..00000000 --- a/client/command.c +++ /dev/null @@ -1,3084 +0,0 @@ -//----------------------------------------------------------------------------- -// The actual command interpeter for what the user types at the command line. -// Jonathan Westhues, Sept 2005 -// Edits by Gerhard de Koning Gans, Sep 2007 (##) -//----------------------------------------------------------------------------- -#ifdef WIN32 -#include -#endif -#include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "../common/iso14443_crc.c" -#include "../common/crc16.c" -#include "../include/usb_cmd.h" - -#define arraylen(x) (sizeof(x)/sizeof((x)[0])) -#define BIT(x) GraphBuffer[x * clock] -#define BITS (GraphTraceLen / clock) -#define SAMPLE_BUFFER_SIZE 64 // XXX check this - -int go = 0; -static int CmdHisamplest(char *str, int nrlow); -unsigned int current_command = CMD_UNKNOWN; -unsigned int received_command = CMD_UNKNOWN; -static uint8_t sample_buf[SAMPLE_BUFFER_SIZE]; - -void wait_for_response(uint32_t response_type) -{ - while (received_command != response_type) { -#ifdef WIN32 - UsbCommand c; - if (ReceiveCommandPoll(&c)) - UsbCommandReceived(&c); - Sleep(0); -#else - usleep(10000); // XXX ugh -#endif - } - received_command = CMD_UNKNOWN; -} - -static void GetFromBigBuf(uint8_t *dest, int bytes) -{ - int n = bytes/4; - - if(n % 48 != 0) { - PrintToScrollback("bad len in GetFromBigBuf"); - return; - } - - int i; - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - - memcpy(dest+(i*4), sample_buf, 48); - } -} - -static void CmdReset(char *str) -{ - UsbCommand c = {CMD_HARDWARE_RESET}; - SendCommand(&c); -} - -static void CmdBuffClear(char *str) -{ - UsbCommand c = {CMD_BUFF_CLEAR}; - SendCommand(&c); - CmdClearGraph(true); -} - -static void CmdQuit(char *str) -{ - exit(0); -} - -static void CmdHIDdemodFSK(char *str) -{ - UsbCommand c={CMD_HID_DEMOD_FSK}; - SendCommand(&c); -} - -static void CmdTune(char *str) -{ - UsbCommand c={CMD_MEASURE_ANTENNA_TUNING}; - SendCommand(&c); -} - -static void CmdHiTune(char *str) -{ - UsbCommand c={CMD_MEASURE_ANTENNA_TUNING_HF}; - SendCommand(&c); -} - -static void CmdHi15read(char *str) -{ - UsbCommand c={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693}; - SendCommand(&c); -} - -static void CmdHi14read(char *str) -{ - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - - -/* New command to read the contents of a SRI512 tag - * SRI512 tags are ISO14443-B modulated memory tags, - * this command just dumps the contents of the memory - */ -static void CmdSri512read(char *str) -{ - UsbCommand c={CMD_READ_SRI512_TAG, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -/* New command to read the contents of a SRIX4K tag - * SRIX4K tags are ISO14443-B modulated memory tags, - * this command just dumps the contents of the memory/ - */ -static void CmdSrix4kread(char *str) -{ - UsbCommand c={CMD_READ_SRIX4K_TAG, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi14areader(char *str) -{ - UsbCommand c={CMD_READER_ISO_14443a, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi14amifare(char *str) -{ - UsbCommand c={CMD_READER_MIFARE, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi15reader(char *str) -{ - UsbCommand c={CMD_READER_ISO_15693, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi15tag(char *str) -{ - UsbCommand c={CMD_SIMTAG_ISO_15693, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi14read_sim(char *str) -{ - UsbCommand c={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdHi14readt(char *str) -{ - UsbCommand c={CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); - - //CmdHisamplest(str); - while(CmdHisamplest(str,strtol(str, NULL, 0))==0) { - SendCommand(&c); - } - RepaintGraphWindow(); -} - -static void CmdHisimlisten(char *str) -{ - UsbCommand c={CMD_SIMULATE_TAG_HF_LISTEN}; - SendCommand(&c); -} - -static void CmdHi14sim(char *str) -{ - UsbCommand c={CMD_SIMULATE_TAG_ISO_14443}; - SendCommand(&c); -} - -static void CmdHi14asim(char *str) // ## simulate iso14443a tag -{ // ## greg - added ability to specify tag UID - - unsigned int hi=0, lo=0; - int n=0, i=0; - while (sscanf(&str[i++], "%1x", &n ) == 1) { - hi=(hi<<4)|(lo>>28); - lo=(lo<<4)|(n&0xf); - } - - // c.arg should be set to *str or convert *str to the correct format for a uid - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a, {hi, lo, 0}}; - PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo); - SendCommand(&c); -} - -static void CmdHi14snoop(char *str) -{ - UsbCommand c={CMD_SNOOP_ISO_14443}; - SendCommand(&c); -} - -static void CmdHi14asnoop(char *str) -{ - UsbCommand c={CMD_SNOOP_ISO_14443a}; - SendCommand(&c); -} - -static void CmdLegicRfRead(char *str) -{ - UsbCommand c={CMD_READER_LEGIC_RF}; - SendCommand(&c); -} - -static void CmdFPGAOff(char *str) // ## FPGA Control -{ - UsbCommand c={CMD_FPGA_MAJOR_MODE_OFF}; - SendCommand(&c); -} - -/* clear out our graph window */ -int CmdClearGraph(int redraw) -{ - int gtl = GraphTraceLen; - GraphTraceLen = 0; - - if (redraw) - RepaintGraphWindow(); - - return gtl; -} - -/* write a bit to the graph */ -static void CmdAppendGraph(int redraw, int clock, int bit) -{ - int i; - - for (i = 0; i < (int)(clock/2); i++) - GraphBuffer[GraphTraceLen++] = bit ^ 1; - - for (i = (int)(clock/2); i < clock; i++) - GraphBuffer[GraphTraceLen++] = bit; - - if (redraw) - RepaintGraphWindow(); -} - -/* Function is equivalent of loread + losamples + em410xread - * looped until an EM410x tag is detected */ -static void CmdEM410xwatch(char *str) -{ - char *zero = ""; - char *twok = "2000"; - go = 1; - - do - { - CmdLoread(zero); - CmdLosamples(twok); - CmdEM410xread(zero); - } while (go); -} - -/* Read the transmitted data of an EM4x50 tag - * Format: - * - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * CCCCCCCC <- column parity bits - * 0 <- stop bit - * LW <- Listen Window - * - * This pattern repeats for every block of data being transmitted. - * Transmission starts with two Listen Windows (LW - a modulated - * pattern of 320 cycles each (32/32/128/64/64)). - * - * Note that this data may or may not be the UID. It is whatever data - * is stored in the blocks defined in the control word First and Last - * Word Read values. UID is stored in block 32. - */ -static void CmdEM4x50read(char *str) -{ - int i, j, startblock, clock, skip, block, start, end, low, high; - bool complete= false; - int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; - char tmp[6]; - - high= low= 0; - clock= 64; - - /* first get high and low values */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* populate a buffer with pulse lengths */ - i= 0; - j= 0; - while(i < GraphTraceLen) - { - // measure from low to low - while((GraphBuffer[i] > low) && (i low) && (i(MAX_GRAPH_TRACE_LEN/64)) { - break; - } - tmpbuff[j++]= i - start; - } - - /* look for data start - should be 2 pairs of LW (pulses of 192,128) */ - start= -1; - skip= 0; - for (i= 0; i < j - 4 ; ++i) - { - skip += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) - if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) - { - start= i + 3; - break; - } - } - startblock= i + 3; - - /* skip over the remainder of the LW */ - skip += tmpbuff[i+1]+tmpbuff[i+2]; - while(skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low) - ++skip; - skip += 8; - - /* now do it again to find the end */ - end= start; - for (i += 3; i < j - 4 ; ++i) - { - end += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194) - if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130) - { - complete= true; - break; - } - } - - if (start >= 0) - PrintToScrollback("Found data at sample: %i",skip); - else - { - PrintToScrollback("No data found!"); - PrintToScrollback("Try again with more samples."); - return; - } - - if (!complete) - { - PrintToScrollback("*** Warning!"); - PrintToScrollback("Partial data - no end found!"); - PrintToScrollback("Try again with more samples."); - } - - /* get rid of leading crap */ - sprintf(tmp,"%i",skip); - CmdLtrim(tmp); - - /* now work through remaining buffer printing out data blocks */ - block= 0; - i= startblock; - while(block < 6) - { - PrintToScrollback("Block %i:", block); - // mandemod routine needs to be split so we can call it for data - // just print for now for debugging - Cmdmanchesterdemod("i 64"); - skip= 0; - /* look for LW before start of next block */ - for ( ; i < j - 4 ; ++i) - { - skip += tmpbuff[i]; - if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194) - if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130) - break; - } - while(GraphBuffer[skip] > low) - ++skip; - skip += 8; - sprintf(tmp,"%i",skip); - CmdLtrim(tmp); - start += skip; - block++; - } -} - - -/* Read the ID of an EM410x tag. - * Format: - * 1111 1111 1 <-- standard non-repeatable header - * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID - * .... - * CCCC <-- each bit here is parity for the 10 bits above in corresponding column - * 0 <-- stop bit, end of tag - */ -static void CmdEM410xread(char *str) -{ - int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low; - int parity[4]; - char id[11]; - int retested = 0; - int BitStream[MAX_GRAPH_TRACE_LEN]; - high = low = 0; - - /* Detect high and lows and clock */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* get clock */ - clock = GetClock(str, high); - - /* parity for our 4 columns */ - parity[0] = parity[1] = parity[2] = parity[3] = 0; - header = rows = 0; - - /* manchester demodulate */ - bit = bit2idx = 0; - for (i = 0; i < (int)(GraphTraceLen / clock); i++) - { - hithigh = 0; - hitlow = 0; - first = 1; - - /* Find out if we hit both high and low peaks */ - for (j = 0; j < clock; j++) - { - if (GraphBuffer[(i * clock) + j] == high) - hithigh = 1; - else if (GraphBuffer[(i * clock) + j] == low) - hitlow = 1; - - /* it doesn't count if it's the first part of our read - because it's really just trailing from the last sequence */ - if (first && (hithigh || hitlow)) - hithigh = hitlow = 0; - else - first = 0; - - if (hithigh && hitlow) - break; - } - - /* If we didn't hit both high and low peaks, we had a bit transition */ - if (!hithigh || !hitlow) - bit ^= 1; - - BitStream[bit2idx++] = bit; - } - -retest: - /* We go till 5 before the graph ends because we'll get that far below */ - for (i = 1; i < bit2idx - 5; i++) - { - /* Step 2: We have our header but need our tag ID */ - if (header == 9 && rows < 10) - { - /* Confirm parity is correct */ - if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4]) - { - /* Read another byte! */ - sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3])); - rows++; - - /* Keep parity info */ - parity[0] ^= BitStream[i]; - parity[1] ^= BitStream[i+1]; - parity[2] ^= BitStream[i+2]; - parity[3] ^= BitStream[i+3]; - - /* Move 4 bits ahead */ - i += 4; - } - - /* Damn, something wrong! reset */ - else - { - PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i); - - /* Start back rows * 5 + 9 header bits, -1 to not start at same place */ - i -= 9 + (5 * rows) - 5; - - rows = header = 0; - } - } - - /* Step 3: Got our 40 bits! confirm column parity */ - else if (rows == 10) - { - /* We need to make sure our 4 bits of parity are correct and we have a stop bit */ - if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] && - BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] && - BitStream[i+4] == 0) - { - /* Sweet! */ - PrintToScrollback("EM410x Tag ID: %s", id); - - /* Stop any loops */ - go = 0; - return; - } - - /* Crap! Incorrect parity or no stop bit, start all over */ - else - { - rows = header = 0; - - /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */ - i -= 59; - } - } - - /* Step 1: get our header */ - else if (header < 9) - { - /* Need 9 consecutive 1's */ - if (BitStream[i] == 1) - header++; - - /* We don't have a header, not enough consecutive 1 bits */ - else - header = 0; - } - } - - /* if we've already retested after flipping bits, return */ - if (retested++) - return; - - /* if this didn't work, try flipping bits */ - for (i = 0; i < bit2idx; i++) - BitStream[i] ^= 1; - - goto retest; -} - -/* emulate an EM410X tag - * Format: - * 1111 1111 1 <-- standard non-repeatable header - * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID - * .... - * CCCC <-- each bit here is parity for the 10 bits above in corresponding column - * 0 <-- stop bit, end of tag - */ -static void CmdEM410xsim(char *str) -{ - int i, n, j, h, binary[4], parity[4]; - - /* clock is 64 in EM410x tags */ - int clock = 64; - - /* clear our graph */ - CmdClearGraph(0); - - /* write it out a few times */ - for (h = 0; h < 4; h++) - { - /* write 9 start bits */ - for (i = 0; i < 9; i++) - CmdAppendGraph(0, clock, 1); - - /* for each hex char */ - parity[0] = parity[1] = parity[2] = parity[3] = 0; - for (i = 0; i < 10; i++) - { - /* read each hex char */ - sscanf(&str[i], "%1x", &n); - for (j = 3; j >= 0; j--, n/= 2) - binary[j] = n % 2; - - /* append each bit */ - CmdAppendGraph(0, clock, binary[0]); - CmdAppendGraph(0, clock, binary[1]); - CmdAppendGraph(0, clock, binary[2]); - CmdAppendGraph(0, clock, binary[3]); - - /* append parity bit */ - CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); - - /* keep track of column parity */ - parity[0] ^= binary[0]; - parity[1] ^= binary[1]; - parity[2] ^= binary[2]; - parity[3] ^= binary[3]; - } - - /* parity columns */ - CmdAppendGraph(0, clock, parity[0]); - CmdAppendGraph(0, clock, parity[1]); - CmdAppendGraph(0, clock, parity[2]); - CmdAppendGraph(0, clock, parity[3]); - - /* stop bit */ - CmdAppendGraph(0, clock, 0); - } - - /* modulate that biatch */ - Cmdmanchestermod(""); - - /* booyah! */ - RepaintGraphWindow(); - - CmdLosim(""); -} - -/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */ -static void CmdLosimManchester(char *str) -{ - static int clock, gap; - static char data[1024], gapstring[8]; - int i; - - /* get settings/bits */ - sscanf(str, "%i %s %i", &clock, &data[0], &gap); - - /* clear our graph */ - CmdClearGraph(0); - - /* fill it with our bitstream */ - for (i= 0; i < strlen(data) ; ++i) - CmdAppendGraph(0, clock, data[i]- '0'); - - /* modulate */ - Cmdmanchestermod(""); - - /* show what we've done */ - RepaintGraphWindow(); - - /* simulate */ - sprintf(&gapstring[0], "%i", gap); - CmdLosim(gapstring); -} - -static void ChkBitstream(char *str) -{ - int i; - - /* convert to bitstream if necessary */ - for (i = 0; i < (int)(GraphTraceLen / 2); i++) - { - if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) - { - Cmdbitstream(str); - break; - } - } -} - -static void CmdLosim(char *str) -{ - int i; - static int gap; - - sscanf(str,"%i",&gap); - - /* convert to bitstream if necessary */ - ChkBitstream(str); - - PrintToScrollback("Sending data, please wait..."); - for (i = 0; i < GraphTraceLen; i += 48) { - UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}}; - int j; - for(j = 0; j < 48; j++) { - c.d.asBytes[j] = GraphBuffer[i+j]; - } - SendCommand(&c); - wait_for_response(CMD_ACK); - } - - PrintToScrollback("Starting simulator..."); - UsbCommand c={CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}}; - SendCommand(&c); -} - -static void CmdLosimBidir(char *str) -{ - /* Set ADC to twice the carrier for a slight supersampling */ - UsbCommand c={CMD_LF_SIMULATE_BIDIR, {47, 384, 0}}; - SendCommand(&c); -} - -static void CmdLoread(char *str) -{ - UsbCommand c={CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; - // 'h' means higher-low-frequency, 134 kHz - if(*str == 'h') { - c.arg[0] = 1; - } else if (*str == '\0') { - c.arg[0] = 0; - } else { - PrintToScrollback("use 'loread' or 'loread h'"); - return; - } - SendCommand(&c); -} - -static void CmdDetectReader(char *str) -{ - UsbCommand c={CMD_LISTEN_READER_FIELD}; - // 'l' means LF - 125/134 kHz - if(*str == 'l') { - c.arg[0] = 1; - } else if (*str == 'h') { - c.arg[0] = 2; - } else if (*str != '\0') { - PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); - return; - } - SendCommand(&c); -} - -/* send a command before reading */ -static void CmdLoCommandRead(char *str) -{ - static char dummy[3]; - - dummy[0]= ' '; - - UsbCommand c={CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K}; - sscanf(str, "%i %i %i %s %s", &c.arg[0], &c.arg[1], &c.arg[2], (char *) &c.d.asBytes,(char *) &dummy+1); - // in case they specified 'h' - strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy); - SendCommand(&c); -} - -static void CmdLosamples(char *str) -{ - int cnt = 0; - int i, j, n; - - n=strtol(str, NULL, 0); - if (n==0) n=128; - if (n>16000) n=16000; - - PrintToScrollback("Reading %d samples\n", n); - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = ((int)sample_buf[j]) - 128; - } - } - PrintToScrollback("Done!\n"); - GraphTraceLen = n*4; - RepaintGraphWindow(); -} - -static void CmdBitsamples(char *str) -{ - int cnt = 0; - int i, j, k, n; - - n = 3072; - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - - for(j = 0; j < 48; j++) { - for(k = 0; k < 8; k++) { - if(sample_buf[j] & (1 << (7 - k))) { - GraphBuffer[cnt++] = 1; - } else { - GraphBuffer[cnt++] = 0; - } - } - } - } - GraphTraceLen = cnt; - RepaintGraphWindow(); -} - -static void CmdHisamples(char *str) -{ - int cnt = 0; - int i, j, n; - - n = 1000; - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = (int)(sample_buf[j]); - } - } - - GraphTraceLen = n*4; - RepaintGraphWindow(); -} - -static int CmdHisamplest(char *str, int nrlow) -{ - int cnt = 0; - int t1, t2; - int i, j, n; - int hasbeennull; - int show; - - n = 1000; - hasbeennull = 0; - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - for(j = 0; j < 48; j++) { - t2 = (int)(sample_buf[j]); - if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; } - - show = 0; - switch(show) { - case 0: - // combined - t1 = (t2 & 0x80) ^ (t2 & 0x20); - t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20); - break; - - case 1: - // only reader - t1 = (t2 & 0x80); - t2 = ((t2 << 1) & 0x80); - break; - - case 2: - // only tag - t1 = (t2 & 0x20); - t2 = ((t2 << 1) & 0x20); - break; - - case 3: - // both, but tag with other algorithm - t1 = (t2 & 0x80) ^ (t2 & 0x08); - t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08); - break; - } - - GraphBuffer[cnt++] = t1; - GraphBuffer[cnt++] = t2; - } - } - GraphTraceLen = n*4; -// 1130 - if(hasbeennull>nrlow || nrlow==0) { - PrintToScrollback("hasbeennull=%d", hasbeennull); - return 1; - } - else { - return 0; - } -} - - -static void CmdHexsamples(char *str) -{ - int i, j, n; - int requested = 0; - int offset = 0; - sscanf(str, "%i %i", &requested, &offset); - if (offset % 4!=0) { - PrintToScrollback("Offset must be a multiple of 4"); - return; - } - offset = offset/4; - - int delivered = 0; - - if (requested == 0) { - n = 12; - requested = 12; - } else { - n = requested/4; - } - - for(i = offset; i < n+offset; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - for (j = 0; j < 48; j += 8) { - PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", - sample_buf[j+0], - sample_buf[j+1], - sample_buf[j+2], - sample_buf[j+3], - sample_buf[j+4], - sample_buf[j+5], - sample_buf[j+6], - sample_buf[j+7], - sample_buf[j+8] - ); - delivered += 8; - if (delivered >= requested) - break; - } - if (delivered >= requested) - break; - } -} - -static void CmdHisampless(char *str) -{ - int cnt = 0; - int i, j; - int n = strtol(str, NULL, 0); - - if(n == 0) { - n = 1000; - } else { - n/= 4; - } - - for(i = 0; i < n; i += 12) { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; - SendCommand(&c); - wait_for_response(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = (int)(sample_buf[j]); - } - } - GraphTraceLen = cnt; - - RepaintGraphWindow(); -} - -static uint16_t Iso15693Crc(uint8_t *v, int n) -{ - uint32_t reg; - int i, j; - - reg = 0xffff; - for(i = 0; i < n; i++) { - reg = reg ^ ((uint32_t)v[i]); - for (j = 0; j < 8; j++) { - if (reg & 0x0001) { - reg = (reg >> 1) ^ 0x8408; - } else { - reg = (reg >> 1); - } - } - } - - return (uint16_t)~reg; -} - -static void CmdHi14bdemod(char *str) -{ - int i, j, iold; - int isum, qsum; - int outOfWeakAt; - bool negateI, negateQ; - - uint8_t data[256]; - int dataLen=0; - - // As received, the samples are pairs, correlations against I and Q - // square waves. So estimate angle of initial carrier (or just - // quadrant, actually), and then do the demod. - - // First, estimate where the tag starts modulating. - for(i = 0; i < GraphTraceLen; i += 2) { - if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) { - break; - } - } - if(i >= GraphTraceLen) { - PrintToScrollback("too weak to sync"); - return; - } - PrintToScrollback("out of weak at %d", i); - outOfWeakAt = i; - - // Now, estimate the phase in the initial modulation of the tag - isum = 0; - qsum = 0; - for(; i < (outOfWeakAt + 16); i += 2) { - isum += GraphBuffer[i+0]; - qsum += GraphBuffer[i+1]; - } - negateI = (isum < 0); - negateQ = (qsum < 0); - - // Turn the correlation pairs into soft decisions on the bit. - j = 0; - for(i = 0; i < GraphTraceLen/2; i++) { - int si = GraphBuffer[j]; - int sq = GraphBuffer[j+1]; - if(negateI) si = -si; - if(negateQ) sq = -sq; - GraphBuffer[i] = si + sq; - j += 2; - } - GraphTraceLen = i; - - i = outOfWeakAt/2; - while(GraphBuffer[i] > 0 && i < GraphTraceLen) - i++; - if(i >= GraphTraceLen) goto demodError; - - iold = i; - while(GraphBuffer[i] < 0 && i < GraphTraceLen) - i++; - if(i >= GraphTraceLen) goto demodError; - if((i - iold) > 23) goto demodError; - - PrintToScrollback("make it to demod loop"); - - for(;;) { - iold = i; - while(GraphBuffer[i] >= 0 && i < GraphTraceLen) - i++; - if(i >= GraphTraceLen) goto demodError; - if((i - iold) > 6) goto demodError; - - uint16_t shiftReg = 0; - if(i + 20 >= GraphTraceLen) goto demodError; - - for(j = 0; j < 10; j++) { - int soft = GraphBuffer[i] + GraphBuffer[i+1]; - - if(abs(soft) < ((abs(isum) + abs(qsum))/20)) { - PrintToScrollback("weak bit"); - } - - shiftReg >>= 1; - if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) { - shiftReg |= 0x200; - } - - i+= 2; - } - - if( (shiftReg & 0x200) && - !(shiftReg & 0x001)) - { - // valid data byte, start and stop bits okay - PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff); - data[dataLen++] = (shiftReg >> 1) & 0xff; - if(dataLen >= sizeof(data)) { - return; - } - } else if(shiftReg == 0x000) { - // this is EOF - break; - } else { - goto demodError; - } - } - - uint8_t first, second; - ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second); - PrintToScrollback("CRC: %02x %02x (%s)\n", first, second, - (first == data[dataLen-2] && second == data[dataLen-1]) ? - "ok" : "****FAIL****"); - - RepaintGraphWindow(); - return; - -demodError: - PrintToScrollback("demod error"); - RepaintGraphWindow(); -} - -static void CmdHi14list(char *str) -{ - uint8_t got[960]; - GetFromBigBuf(got, sizeof(got)); - - PrintToScrollback("recorded activity:"); - PrintToScrollback(" time :rssi: who bytes"); - PrintToScrollback("---------+----+----+-----------"); - - int i = 0; - int prev = -1; - - for(;;) { - if(i >= 900) { - break; - } - - bool isResponse; - int timestamp = *((uint32_t *)(got+i)); - if(timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - int metric = *((uint32_t *)(got+i+4)); - - int len = got[i+8]; - - if(len > 100) { - break; - } - if(i + len >= 900) { - break; - } - - uint8_t *frame = (got+i+9); - - char line[1000] = ""; - int j; - for(j = 0; j < len; j++) { - sprintf(line+(j*3), "%02x ", frame[j]); - } - - char *crc; - if(len > 2) { - uint8_t b1, b2; - ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2); - if(b1 != frame[len-2] || b2 != frame[len-1]) { - crc = "**FAIL CRC**"; - } else { - crc = ""; - } - } else { - crc = "(SHORT)"; - } - - char metricString[100]; - if(isResponse) { - sprintf(metricString, "%3d", metric); - } else { - strcpy(metricString, " "); - } - - PrintToScrollback(" +%7d: %s: %s %s %s", - (prev < 0 ? 0 : timestamp - prev), - metricString, - (isResponse ? "TAG" : " "), line, crc); - - prev = timestamp; - i += (len + 9); - } -} - -static void CmdHi14alist(char *str) -{ - uint8_t got[1920]; - GetFromBigBuf(got, sizeof(got)); - - PrintToScrollback("recorded activity:"); - PrintToScrollback(" ETU :rssi: who bytes"); - PrintToScrollback("---------+----+----+-----------"); - - int i = 0; - int prev = -1; - - for(;;) { - if(i >= 1900) { - break; - } - - bool isResponse; - int timestamp = *((uint32_t *)(got+i)); - if(timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - - int metric = 0; - int parityBits = *((uint32_t *)(got+i+4)); - // 4 bytes of additional information... - // maximum of 32 additional parity bit information - // - // TODO: - // at each quarter bit period we can send power level (16 levels) - // or each half bit period in 256 levels. - - - int len = got[i+8]; - - if(len > 100) { - break; - } - if(i + len >= 1900) { - break; - } - - uint8_t *frame = (got+i+9); - - // Break and stick with current result if buffer was not completely full - if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; } - - char line[1000] = ""; - int j; - for(j = 0; j < len; j++) { - int oddparity = 0x01; - int k; - - for(k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } - - //if((parityBits >> (len - j - 1)) & 0x01) { - if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } - else { - sprintf(line+(j*4), "%02x ", frame[j]); - } - } - - char *crc; - crc = ""; - if(len > 2) { - uint8_t b1, b2; - for(j = 0; j < (len - 1); j++) { - // gives problems... search for the reason.. - /*if(frame[j] == 0xAA) { - switch(frame[j+1]) { - case 0x01: - crc = "[1] Two drops close after each other"; - break; - case 0x02: - crc = "[2] Potential SOC with a drop in second half of bitperiod"; - break; - case 0x03: - crc = "[3] Segment Z after segment X is not possible"; - break; - case 0x04: - crc = "[4] Parity bit of a fully received byte was wrong"; - break; - default: - crc = "[?] Unknown error"; - break; - } - break; - }*/ - } - - if(strlen(crc)==0) { - ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2); - if(b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (isResponse & (len < 6)) ? "" : " !crc"; - } else { - crc = ""; - } - } - } else { - crc = ""; // SHORT - } - - char metricString[100]; - if(isResponse) { - sprintf(metricString, "%3d", metric); - } else { - strcpy(metricString, " "); - } - - PrintToScrollback(" +%7d: %s: %s %s %s", - (prev < 0 ? 0 : (timestamp - prev)), - metricString, - (isResponse ? "TAG" : " "), line, crc); - - prev = timestamp; - i += (len + 9); - } - CommandFinished = 1; -} - -static void CmdHi15demod(char *str) -{ - // The sampling rate is 106.353 ksps/s, for T = 18.8 us - - // SOF defined as - // 1) Unmodulated time of 56.64us - // 2) 24 pulses of 423.75khz - // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) - - static const int FrameSOF[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; - static const int Logic0[] = { - 1, 1, 1, 1, - 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1 - }; - static const int Logic1[] = { - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; - - // EOF defined as - // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) - // 2) 24 pulses of 423.75khz - // 3) Unmodulated time of 56.64us - - static const int FrameEOF[] = { - 1, 1, 1, 1, - 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; - - int i, j; - int max = 0, maxPos; - - int skip = 4; - - if(GraphTraceLen < 1000) return; - - // First, correlate for SOF - for(i = 0; i < 100; i++) { - int corr = 0; - for(j = 0; j < arraylen(FrameSOF); j += skip) { - corr += FrameSOF[j]*GraphBuffer[i+(j/skip)]; - } - if(corr > max) { - max = corr; - maxPos = i; - } - } - PrintToScrollback("SOF at %d, correlation %d", maxPos, - max/(arraylen(FrameSOF)/skip)); - - i = maxPos + arraylen(FrameSOF)/skip; - int k = 0; - uint8_t outBuf[20]; - memset(outBuf, 0, sizeof(outBuf)); - uint8_t mask = 0x01; - for(;;) { - int corr0 = 0, corr1 = 0, corrEOF = 0; - for(j = 0; j < arraylen(Logic0); j += skip) { - corr0 += Logic0[j]*GraphBuffer[i+(j/skip)]; - } - for(j = 0; j < arraylen(Logic1); j += skip) { - corr1 += Logic1[j]*GraphBuffer[i+(j/skip)]; - } - for(j = 0; j < arraylen(FrameEOF); j += skip) { - corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)]; - } - // Even things out by the length of the target waveform. - corr0 *= 4; - corr1 *= 4; - - if(corrEOF > corr1 && corrEOF > corr0) { - PrintToScrollback("EOF at %d", i); - break; - } else if(corr1 > corr0) { - i += arraylen(Logic1)/skip; - outBuf[k] |= mask; - } else { - i += arraylen(Logic0)/skip; - } - mask <<= 1; - if(mask == 0) { - k++; - mask = 0x01; - } - if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) { - PrintToScrollback("ran off end!"); - break; - } - } - if(mask != 0x01) { - PrintToScrollback("error, uneven octet! (discard extra bits!)"); - PrintToScrollback(" mask=%02x", mask); - } - PrintToScrollback("%d octets", k); - - for(i = 0; i < k; i++) { - PrintToScrollback("# %2d: %02x ", i, outBuf[i]); - } - PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2)); -} - -static void CmdFSKdemod(char *cmdline) -{ - static const int LowTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 - }; - static const int HighTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, -1, - }; - - int lowLen = sizeof(LowTone)/sizeof(int); - int highLen = sizeof(HighTone)/sizeof(int); - int convLen = (highLen>lowLen)?highLen:lowLen; - uint32_t hi = 0, lo = 0; - - int i, j; - int minMark=0, maxMark=0; - - for(i = 0; i < GraphTraceLen - convLen; i++) { - int lowSum = 0, highSum = 0; - - for(j = 0; j < lowLen; j++) { - lowSum += LowTone[j]*GraphBuffer[i+j]; - } - for(j = 0; j < highLen; j++) { - highSum += HighTone[j]*GraphBuffer[i+j]; - } - lowSum = abs((100*lowSum) / lowLen); - highSum = abs((100*highSum) / highLen); - GraphBuffer[i] = (highSum << 16) | lowSum; - } - - for(i = 0; i < GraphTraceLen - convLen - 16; i++) { - int j; - int lowTot = 0, highTot = 0; - // 10 and 8 are f_s divided by f_l and f_h, rounded - for(j = 0; j < 10; j++) { - lowTot += (GraphBuffer[i+j] & 0xffff); - } - for(j = 0; j < 8; j++) { - highTot += (GraphBuffer[i+j] >> 16); - } - GraphBuffer[i] = lowTot - highTot; - if (GraphBuffer[i]>maxMark) maxMark=GraphBuffer[i]; - if (GraphBuffer[i] max) { - max = dec; - maxPos = i; - } - } - - // place start of bit sync marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos+1] = minMark; - - maxPos += j; - - // place end of bit sync marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos+1] = minMark; - - PrintToScrollback("actual data bits start at sample %d", maxPos); - PrintToScrollback("length %d/%d", highLen, lowLen); - - uint8_t bits[46]; - bits[sizeof(bits)-1] = '\0'; - - // find bit pairs and manchester decode them - for(i = 0; i < arraylen(bits)-1; i++) { - int dec = 0; - for(j = 0; j < lowLen; j++) { - dec -= GraphBuffer[maxPos+j]; - } - for(; j < lowLen + highLen; j++) { - dec += GraphBuffer[maxPos+j]; - } - maxPos += j; - // place inter bit marker in graph - GraphBuffer[maxPos] = maxMark; - GraphBuffer[maxPos+1] = minMark; - - // hi and lo form a 64 bit pair - hi = (hi<<1)|(lo>>31); - lo = (lo<<1); - // store decoded bit as binary (in hi/lo) and text (in bits[]) - if(dec<0) { - bits[i] = '1'; - lo|=1; - } else { - bits[i] = '0'; - } - } - PrintToScrollback("bits: '%s'", bits); - PrintToScrollback("hex: %08x %08x", hi, lo); -} - -// read a TI tag and return its ID -static void CmdTIRead(char *str) -{ - UsbCommand c={CMD_READ_TI_TYPE}; - SendCommand(&c); -} - -// write new data to a r/w TI tag -static void CmdTIWrite(char *str) -{ - UsbCommand c={CMD_WRITE_TI_TYPE}; - int res=0; - - res = sscanf(str, "0x%x 0x%x 0x%x ", &c.arg[0], &c.arg[1], &c.arg[2]); - if (res == 2) c.arg[2]=0; - if (res<2) - PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third"); - else - SendCommand(&c); -} - -static void CmdTIDemod(char *cmdline) -{ - /* MATLAB as follows: -f_s = 2000000; % sampling frequency -f_l = 123200; % low FSK tone -f_h = 134200; % high FSK tone - -T_l = 119e-6; % low bit duration -T_h = 130e-6; % high bit duration - -l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s); -h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s); - -l = sign(sin(cumsum(l))); -h = sign(sin(cumsum(h))); - */ - -// 2M*16/134.2k = 238 - static const int LowTone[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 - }; -// 2M*16/123.2k = 260 - static const int HighTone[] = { - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1 - }; - int lowLen = sizeof(LowTone)/sizeof(int); - int highLen = sizeof(HighTone)/sizeof(int); - int convLen = (highLen>lowLen)?highLen:lowLen; - uint16_t crc; - int i, j, TagType; - int lowSum = 0, highSum = 0;; - int lowTot = 0, highTot = 0; - - for(i = 0; i < GraphTraceLen - convLen; i++) { - lowSum = 0; - highSum = 0;; - - for(j = 0; j < lowLen; j++) { - lowSum += LowTone[j]*GraphBuffer[i+j]; - } - for(j = 0; j < highLen; j++) { - highSum += HighTone[j]*GraphBuffer[i+j]; - } - lowSum = abs((100*lowSum) / lowLen); - highSum = abs((100*highSum) / highLen); - lowSum = (lowSum<0)?-lowSum:lowSum; - highSum = (highSum<0)?-highSum:highSum; - - GraphBuffer[i] = (highSum << 16) | lowSum; - } - - for(i = 0; i < GraphTraceLen - convLen - 16; i++) { - lowTot = 0; - highTot = 0; - // 16 and 15 are f_s divided by f_l and f_h, rounded - for(j = 0; j < 16; j++) { - lowTot += (GraphBuffer[i+j] & 0xffff); - } - for(j = 0; j < 15; j++) { - highTot += (GraphBuffer[i+j] >> 16); - } - GraphBuffer[i] = lowTot - highTot; - } - - GraphTraceLen -= (convLen + 16); - - RepaintGraphWindow(); - - // TI tag data format is 16 prebits, 8 start bits, 64 data bits, - // 16 crc CCITT bits, 8 stop bits, 15 end bits - - // the 16 prebits are always low - // the 8 start and stop bits of a tag must match - // the start/stop prebits of a ro tag are 01111110 - // the start/stop prebits of a rw tag are 11111110 - // the 15 end bits of a ro tag are all low - // the 15 end bits of a rw tag match bits 15-1 of the data bits - - // Okay, so now we have unsliced soft decisions; - // find bit-sync, and then get some bits. - // look for 17 low bits followed by 6 highs (common pattern for ro and rw tags) - int max = 0, maxPos = 0; - for(i = 0; i < 6000; i++) { - int j; - int dec = 0; - // searching 17 consecutive lows - for(j = 0; j < 17*lowLen; j++) { - dec -= GraphBuffer[i+j]; - } - // searching 7 consecutive highs - for(; j < 17*lowLen + 6*highLen; j++) { - dec += GraphBuffer[i+j]; - } - if(dec > max) { - max = dec; - maxPos = i; - } - } - - // place a marker in the buffer to visually aid location - // of the start of sync - GraphBuffer[maxPos] = 800; - GraphBuffer[maxPos+1] = -800; - - // advance pointer to start of actual data stream (after 16 pre and 8 start bits) - maxPos += 17*lowLen; - maxPos += 6*highLen; - - // place a marker in the buffer to visually aid location - // of the end of sync - GraphBuffer[maxPos] = 800; - GraphBuffer[maxPos+1] = -800; - - PrintToScrollback("actual data bits start at sample %d", maxPos); - - PrintToScrollback("length %d/%d", highLen, lowLen); - - uint8_t bits[1+64+16+8+16]; - bits[sizeof(bits)-1] = '\0'; - - uint32_t shift3 = 0x7e000000, shift2 = 0, shift1 = 0, shift0 = 0; - - for(i = 0; i < arraylen(bits)-1; i++) { - int high = 0; - int low = 0; - int j; - for(j = 0; j < lowLen; j++) { - low -= GraphBuffer[maxPos+j]; - } - for(j = 0; j < highLen; j++) { - high += GraphBuffer[maxPos+j]; - } - - if(high > low) { - bits[i] = '1'; - maxPos += highLen; - // bitstream arrives lsb first so shift right - shift3 |= (1<<31); - } else { - bits[i] = '.'; - maxPos += lowLen; - } - - // 128 bit right shift register - shift0 = (shift0>>1) | (shift1 << 31); - shift1 = (shift1>>1) | (shift2 << 31); - shift2 = (shift2>>1) | (shift3 << 31); - shift3 >>= 1; - - // place a marker in the buffer between bits to visually aid location - GraphBuffer[maxPos] = 800; - GraphBuffer[maxPos+1] = -800; - } - PrintToScrollback("Info: raw tag bits = %s", bits); - - TagType = (shift3>>8)&0xff; - if ( TagType != ((shift0>>16)&0xff) ) { - PrintToScrollback("Error: start and stop bits do not match!"); - return; - } - else if (TagType == 0x7e) { - PrintToScrollback("Info: Readonly TI tag detected."); - return; - } - else if (TagType == 0xfe) { - PrintToScrollback("Info: Rewriteable TI tag detected."); - - // put 64 bit data into shift1 and shift0 - shift0 = (shift0>>24) | (shift1 << 8); - shift1 = (shift1>>24) | (shift2 << 8); - - // align 16 bit crc into lower half of shift2 - shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff; - - // align 16 bit "end bits" or "ident" into lower half of shift3 - shift3 >>= 16; - - // only 15 bits compare, last bit of ident is not valid - if ( (shift3^shift0)&0x7fff ) { - PrintToScrollback("Error: Ident mismatch!"); - } - // WARNING the order of the bytes in which we calc crc below needs checking - // i'm 99% sure the crc algorithm is correct, but it may need to eat the - // bytes in reverse or something - // calculate CRC - crc=0; - crc = update_crc16(crc, (shift0)&0xff); - crc = update_crc16(crc, (shift0>>8)&0xff); - crc = update_crc16(crc, (shift0>>16)&0xff); - crc = update_crc16(crc, (shift0>>24)&0xff); - crc = update_crc16(crc, (shift1)&0xff); - crc = update_crc16(crc, (shift1>>8)&0xff); - crc = update_crc16(crc, (shift1>>16)&0xff); - crc = update_crc16(crc, (shift1>>24)&0xff); - PrintToScrollback("Info: Tag data = %08X%08X", shift1, shift0); - if (crc != (shift2&0xffff)) { - PrintToScrollback("Error: CRC mismatch, calculated %04X, got ^04X", crc, shift2&0xffff); - } else { - PrintToScrollback("Info: CRC %04X is good", crc); - } - } - else { - PrintToScrollback("Unknown tag type."); - return; - } -} - -static void CmdNorm(char *str) -{ - int i; - int max = INT_MIN, min = INT_MAX; - for(i = 10; i < GraphTraceLen; i++) { - if(GraphBuffer[i] > max) { - max = GraphBuffer[i]; - } - if(GraphBuffer[i] < min) { - min = GraphBuffer[i]; - } - } - if(max != min) { - for(i = 0; i < GraphTraceLen; i++) { - GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/ - (max - min); - } - } - RepaintGraphWindow(); -} - -static void CmdAmp(char *str) -{ - int i, rising, falling; - int max = INT_MIN, min = INT_MAX; - for(i = 10; i < GraphTraceLen; i++) { - if(GraphBuffer[i] > max) { - max = GraphBuffer[i]; - } - if(GraphBuffer[i] < min) { - min = GraphBuffer[i]; - } - } - if(max != min) { - rising= falling= 0; - for(i = 0; i < GraphTraceLen; i++) { - if(GraphBuffer[i+1] < GraphBuffer[i]) { - if(rising) { - GraphBuffer[i]= max; - rising= 0; - } - falling= 1; - } - if(GraphBuffer[i+1] > GraphBuffer[i]) { - if(falling) { - GraphBuffer[i]= min; - falling= 0; - } - rising= 1; - } - } - } - RepaintGraphWindow(); -} - -static void CmdDec(char *str) -{ - int i; - for(i = 0; i < (GraphTraceLen/2); i++) { - GraphBuffer[i] = GraphBuffer[i*2]; - } - GraphTraceLen /= 2; - PrintToScrollback("decimated by 2"); - RepaintGraphWindow(); -} - -static void CmdHpf(char *str) -{ - int i; - int accum = 0; - for(i = 10; i < GraphTraceLen; i++) { - accum += GraphBuffer[i]; - } - accum /= (GraphTraceLen - 10); - for(i = 0; i < GraphTraceLen; i++) { - GraphBuffer[i] -= accum; - } - - RepaintGraphWindow(); -} - -static void CmdZerocrossings(char *str) -{ - int i; - // Zero-crossings aren't meaningful unless the signal is zero-mean. - CmdHpf(""); - - int sign = 1; - int zc = 0; - int lastZc = 0; - for(i = 0; i < GraphTraceLen; i++) { - if(GraphBuffer[i]*sign >= 0) { - // No change in sign, reproduce the previous sample count. - zc++; - GraphBuffer[i] = lastZc; - } else { - // Change in sign, reset the sample count. - sign = -sign; - GraphBuffer[i] = lastZc; - if(sign > 0) { - lastZc = zc; - zc = 0; - } - } - } - - RepaintGraphWindow(); -} - -static void CmdThreshold(char *str) -{ - int i; - int threshold = atoi(str); - - for(i = 0; i < GraphTraceLen; i++) { - if(GraphBuffer[i]>= threshold) - GraphBuffer[i]=1; - else - GraphBuffer[i]=-1; - } - RepaintGraphWindow(); -} - -static void CmdLtrim(char *str) -{ - int i; - int ds = atoi(str); - - for(i = ds; i < GraphTraceLen; i++) { - GraphBuffer[i-ds] = GraphBuffer[i]; - } - GraphTraceLen -= ds; - - RepaintGraphWindow(); -} - -static void CmdAutoCorr(char *str) -{ - static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; - - int window = atoi(str); - - if(window == 0) { - PrintToScrollback("needs a window"); - return; - } - - if(window >= GraphTraceLen) { - PrintToScrollback("window must be smaller than trace (%d samples)", - GraphTraceLen); - return; - } - - PrintToScrollback("performing %d correlations", GraphTraceLen - window); - - int i; - for(i = 0; i < GraphTraceLen - window; i++) { - int sum = 0; - int j; - for(j = 0; j < window; j++) { - sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256; - } - CorrelBuffer[i] = sum; - } - GraphTraceLen = GraphTraceLen - window; - memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int)); - - RepaintGraphWindow(); -} - -static void CmdVchdemod(char *str) -{ - // Is this the entire sync pattern, or does this also include some - // data bits that happen to be the same everywhere? That would be - // lovely to know. - static const int SyncPattern[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - // So first, we correlate for the sync pattern, and mark that. - int bestCorrel = 0, bestPos = 0; - int i; - // It does us no good to find the sync pattern, with fewer than - // 2048 samples after it... - for(i = 0; i < (GraphTraceLen-2048); i++) { - int sum = 0; - int j; - for(j = 0; j < arraylen(SyncPattern); j++) { - sum += GraphBuffer[i+j]*SyncPattern[j]; - } - if(sum > bestCorrel) { - bestCorrel = sum; - bestPos = i; - } - } - PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel); - - char bits[257]; - bits[256] = '\0'; - - int worst = INT_MAX; - int worstPos; - - for(i = 0; i < 2048; i += 8) { - int sum = 0; - int j; - for(j = 0; j < 8; j++) { - sum += GraphBuffer[bestPos+i+j]; - } - if(sum < 0) { - bits[i/8] = '.'; - } else { - bits[i/8] = '1'; - } - if(abs(sum) < worst) { - worst = abs(sum); - worstPos = i; - } - } - PrintToScrollback("bits:"); - PrintToScrollback("%s", bits); - PrintToScrollback("worst metric: %d at pos %d", worst, worstPos); - - if(strcmp(str, "clone")==0) { - GraphTraceLen = 0; - char *s; - for(s = bits; *s; s++) { - int j; - for(j = 0; j < 16; j++) { - GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0; - } - } - RepaintGraphWindow(); - } -} - -static void CmdIndalademod(char *str) -{ - // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID - - int state = -1; - int count = 0; - int i, j; - // worst case with GraphTraceLen=64000 is < 4096 - // under normal conditions it's < 2048 - uint8_t rawbits[4096]; - int rawbit = 0; - int worst = 0, worstPos = 0; - PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32); - for(i = 0; i < GraphTraceLen-1; i += 2) { - count+=1; - if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { - if (state == 0) { - for(j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 0; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 1; - count=0; - } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { - if (state == 1) { - for(j = 0; j < count - 8; j += 16) { - rawbits[rawbit++] = 1; - } - if ((abs(count - j)) > worst) { - worst = abs(count - j); - worstPos = i; - } - } - state = 0; - count=0; - } - } - PrintToScrollback("Recovered %d raw bits", rawbit); - PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); - - // Finding the start of a UID - int uidlen, long_wait; - if(strcmp(str, "224") == 0) { - uidlen=224; - long_wait=30; - } else { - uidlen=64; - long_wait=29; - } - int start; - int first = 0; - for(start = 0; start <= rawbit - uidlen; start++) { - first = rawbits[start]; - for(i = start; i < start + long_wait; i++) { - if(rawbits[i] != first) { - break; - } - } - if(i == (start + long_wait)) { - break; - } - } - if(start == rawbit - uidlen + 1) { - PrintToScrollback("nothing to wait for"); - return; - } - - // Inverting signal if needed - if(first == 1) { - for(i = start; i < rawbit; i++) { - rawbits[i] = !rawbits[i]; - } - } - - // Dumping UID - uint8_t bits[224]; - char showbits[225]; - showbits[uidlen]='\0'; - int bit; - i = start; - int times = 0; - if(uidlen > rawbit) { - PrintToScrollback("Warning: not enough raw bits to get a full UID"); - for(bit = 0; bit < rawbit; bit++) { - bits[bit] = rawbits[i++]; - // As we cannot know the parity, let's use "." and "/" - showbits[bit] = '.' + bits[bit]; - } - showbits[bit+1]='\0'; - PrintToScrollback("Partial UID=%s", showbits); - return; - } else { - for(bit = 0; bit < uidlen; bit++) { - bits[bit] = rawbits[i++]; - showbits[bit] = '0' + bits[bit]; - } - times = 1; - } - PrintToScrollback("UID=%s", showbits); - - // Checking UID against next occurences - for(; i + uidlen <= rawbit;) { - int failed = 0; - for(bit = 0; bit < uidlen; bit++) { - if(bits[bit] != rawbits[i++]) { - failed = 1; - break; - } - } - if (failed == 1) { - break; - } - times += 1; - } - PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen); - - // Remodulating for tag cloning - GraphTraceLen = 32*uidlen; - i = 0; - int phase = 0; - for(bit = 0; bit < uidlen; bit++) { - if(bits[bit] == 0) { - phase = 0; - } else { - phase = 1; - } - int j; - for(j = 0; j < 32; j++) { - GraphBuffer[i++] = phase; - phase = !phase; - } - } - - RepaintGraphWindow(); -} - -static void CmdFlexdemod(char *str) -{ - int i; - for(i = 0; i < GraphTraceLen; i++) { - if(GraphBuffer[i] < 0) { - GraphBuffer[i] = -1; - } else { - GraphBuffer[i] = 1; - } - } - -#define LONG_WAIT 100 - int start; - for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) { - int first = GraphBuffer[start]; - for(i = start; i < start + LONG_WAIT; i++) { - if(GraphBuffer[i] != first) { - break; - } - } - if(i == (start + LONG_WAIT)) { - break; - } - } - if(start == GraphTraceLen - LONG_WAIT) { - PrintToScrollback("nothing to wait for"); - return; - } - - GraphBuffer[start] = 2; - GraphBuffer[start+1] = -2; - - uint8_t bits[64]; - - int bit; - i = start; - for(bit = 0; bit < 64; bit++) { - int j; - int sum = 0; - for(j = 0; j < 16; j++) { - sum += GraphBuffer[i++]; - } - if(sum > 0) { - bits[bit] = 1; - } else { - bits[bit] = 0; - } - PrintToScrollback("bit %d sum %d", bit, sum); - } - - for(bit = 0; bit < 64; bit++) { - int j; - int sum = 0; - for(j = 0; j < 16; j++) { - sum += GraphBuffer[i++]; - } - if(sum > 0 && bits[bit] != 1) { - PrintToScrollback("oops1 at %d", bit); - } - if(sum < 0 && bits[bit] != 0) { - PrintToScrollback("oops2 at %d", bit); - } - } - - GraphTraceLen = 32*64; - i = 0; - int phase = 0; - for(bit = 0; bit < 64; bit++) { - if(bits[bit] == 0) { - phase = 0; - } else { - phase = 1; - } - int j; - for(j = 0; j < 32; j++) { - GraphBuffer[i++] = phase; - phase = !phase; - } - } - - RepaintGraphWindow(); -} - -/* - * Generic command to demodulate ASK. - * - * Argument is convention: positive or negative (High mod means zero - * or high mod means one) - * - * Updates the Graph trace with 0/1 values - * - * Arguments: - * c : 0 or 1 - */ - -static void Cmdaskdemod(char *str) { - int i; - int c, high = 0, low = 0; - - // TODO: complain if we do not give 2 arguments here ! - // (AL - this doesn't make sense! we're only using one argument!!!) - sscanf(str, "%i", &c); - - /* Detect high and lows and clock */ - // (AL - clock???) - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - if(c != 0 && c != 1) { - PrintToScrollback("Invalid argument: %s",str); - return; - } - - if (GraphBuffer[0] > 0) { - GraphBuffer[0] = 1-c; - } else { - GraphBuffer[0] = c; - } - for(i=1;i peak) - peak = GraphBuffer[i]; - - for (i = 1; i < GraphTraceLen; i++) - { - /* If this is the beginning of a peak */ - if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak) - { - /* Find lowest difference between peaks */ - if (lastpeak && i - lastpeak < clock) - { - clock = i - lastpeak; - } - lastpeak = i; - } - } - - return clock; -} - -/* Get or auto-detect clock rate */ -int GetClock(char *str, int peak) -{ - int clock; - - sscanf(str, "%i", &clock); - if (!strcmp(str, "")) - clock = 0; - - /* Auto-detect clock */ - if (!clock) - { - clock = detectclock(peak); - - /* Only print this message if we're not looping something */ - if (!go) - PrintToScrollback("Auto-detected clock rate: %d", clock); - } - - return clock; -} - -/* - * Convert to a bitstream - */ -static void Cmdbitstream(char *str) { - int i, j; - int bit; - int gtl; - int clock; - int low = 0; - int high = 0; - int hithigh, hitlow, first; - - /* Detect high and lows and clock */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* Get our clock */ - clock = GetClock(str, high); - - gtl = CmdClearGraph(0); - - bit = 0; - for (i = 0; i < (int)(gtl / clock); i++) - { - hithigh = 0; - hitlow = 0; - first = 1; - - /* Find out if we hit both high and low peaks */ - for (j = 0; j < clock; j++) - { - if (GraphBuffer[(i * clock) + j] == high) - hithigh = 1; - else if (GraphBuffer[(i * clock) + j] == low) - hitlow = 1; - - /* it doesn't count if it's the first part of our read - because it's really just trailing from the last sequence */ - if (first && (hithigh || hitlow)) - hithigh = hitlow = 0; - else - first = 0; - - if (hithigh && hitlow) - break; - } - - /* If we didn't hit both high and low peaks, we had a bit transition */ - if (!hithigh || !hitlow) - bit ^= 1; - - CmdAppendGraph(0, clock, bit); -// for (j = 0; j < (int)(clock/2); j++) -// GraphBuffer[(i * clock) + j] = bit ^ 1; -// for (j = (int)(clock/2); j < clock; j++) -// GraphBuffer[(i * clock) + j] = bit; - } - - RepaintGraphWindow(); -} - -/* Modulate our data into manchester */ -static void Cmdmanchestermod(char *str) -{ - int i, j; - int clock; - int bit, lastbit, wave; - - /* Get our clock */ - clock = GetClock(str, 0); - - wave = 0; - lastbit = 1; - for (i = 0; i < (int)(GraphTraceLen / clock); i++) - { - bit = GraphBuffer[i * clock] ^ 1; - - for (j = 0; j < (int)(clock/2); j++) - GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave; - for (j = (int)(clock/2); j < clock; j++) - GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1; - - /* Keep track of how we start our wave and if we changed or not this time */ - wave ^= bit ^ lastbit; - lastbit = bit; - } - - 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) - * Typical values can be 64, 32, 128... - */ -static void Cmdmanchesterdemod(char *str) { - int i, j, invert= 0; - int bit; - int clock; - int lastval; - int low = 0; - int high = 0; - int hithigh, hitlow, first; - int lc = 0; - int bitidx = 0; - int bit2idx = 0; - int warnings = 0; - - /* check if we're inverting output */ - if(*str == 'i') - { - PrintToScrollback("Inverting output"); - invert= 1; - do - ++str; - while(*str == ' '); // in case a 2nd argument was given - } - - /* 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 high and lows */ - for (i = 0; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } - - /* Get our clock */ - clock = GetClock(str, high); - - int tolerance = clock/4; - - /* Detect first transition */ - /* Lo-Hi (arbitrary) */ - /* skip to the first high */ - for (i= 0; i < GraphTraceLen; i++) - if(GraphBuffer[i] == high) - break; - /* now look for the first low */ - for (; i < GraphTraceLen; i++) - { - if (GraphBuffer[i] == low) - { - lastval = i; - break; - } - } - - /* If we're not working with 1/0s, demod based off clock */ - if (high != 1) - { - bit = 0; /* We assume the 1st bit is zero, it may not be - * the case: this routine (I think) has an init problem. - * Ed. - */ - for (; i < (int)(GraphTraceLen / clock); i++) - { - hithigh = 0; - hitlow = 0; - first = 1; - - /* Find out if we hit both high and low peaks */ - for (j = 0; j < clock; j++) - { - if (GraphBuffer[(i * clock) + j] == high) - hithigh = 1; - else if (GraphBuffer[(i * clock) + j] == low) - hitlow = 1; - - /* it doesn't count if it's the first part of our read - because it's really just trailing from the last sequence */ - if (first && (hithigh || hitlow)) - hithigh = hitlow = 0; - else - first = 0; - - if (hithigh && hitlow) - break; - } - - /* If we didn't hit both high and low peaks, we had a bit transition */ - if (!hithigh || !hitlow) - bit ^= 1; - - BitStream[bit2idx++] = bit ^ invert; - } - } - - /* standard 1/0 bitstream */ - else - { - - /* Then detect duration between 2 successive transitions */ - 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) - if (abs(lc-clock/2) < tolerance) { - // Short pulse : either "1" or "0" - BitStream[bitidx++]=GraphBuffer[i-1]; - } else if (abs(lc-clock) < tolerance) { - // Long pulse: either "11" or "00" - BitStream[bitidx++]=GraphBuffer[i-1]; - BitStream[bitidx++]=GraphBuffer[i-1]; - } else { - // Error - warnings++; - 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)"); - - if (warnings > 100) - { - PrintToScrollback("Error: too many detection errors, aborting."); - return; - } - } - } - } - - // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream - // 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 ^ invert; - } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) { - BitStream[bit2idx++] = 0 ^ invert; - } else { - // We cannot end up in this state, this means we are unsynchronized, - // move up 1 bit: - i++; - warnings++; - PrintToScrollback("Unsynchronized, resync..."); - PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); - - if (warnings > 100) - { - PrintToScrollback("Error: too many decode errors, aborting."); - return; - } - } - } - } - - PrintToScrollback("Manchester decoded bitstream"); - // Now output the bitstream to the scrollback by line of 16 bits - 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", - 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]); - } -} - -/* - * Usage ??? - */ -static void CmdHiddemod(char *str) -{ - if(GraphTraceLen < 4800) { - PrintToScrollback("too short; need at least 4800 samples"); - return; - } - - GraphTraceLen = 4800; - int i; - for(i = 0; i < GraphTraceLen; i++) { - if(GraphBuffer[i] < 0) { - GraphBuffer[i] = 0; - } else { - GraphBuffer[i] = 1; - } - } - RepaintGraphWindow(); -} - -static void CmdPlot(char *str) -{ - ShowGraphWindow(); -} - -static void CmdGrid(char *str) -{ - sscanf(str, "%i %i", &PlotGridX, &PlotGridY); - RepaintGraphWindow(); -} - -static void CmdHide(char *str) -{ - HideGraphWindow(); -} - -static void CmdScale(char *str) -{ - CursorScaleFactor = atoi(str); - if(CursorScaleFactor == 0) { - PrintToScrollback("bad, can't have zero scale"); - CursorScaleFactor = 1; - } - RepaintGraphWindow(); -} - -static void CmdSave(char *str) -{ - FILE *f = fopen(str, "w"); - if(!f) { - PrintToScrollback("couldn't open '%s'", str); - return; - } - int i; - for(i = 0; i < GraphTraceLen; i++) { - fprintf(f, "%d\n", GraphBuffer[i]); - } - fclose(f); - PrintToScrollback("saved to '%s'", str); -} - -static void CmdLoad(char *str) -{ - FILE *f = fopen(str, "r"); - if(!f) { - PrintToScrollback("couldn't open '%s'", str); - return; - } - - GraphTraceLen = 0; - char line[80]; - while(fgets(line, sizeof(line), f)) { - GraphBuffer[GraphTraceLen] = atoi(line); - GraphTraceLen++; - } - fclose(f); - PrintToScrollback("loaded %d samples", GraphTraceLen); - RepaintGraphWindow(); -} - -static void CmdHIDsimTAG(char *str) -{ - unsigned int hi=0, lo=0; - int n=0, i=0; - - while (sscanf(&str[i++], "%1x", &n ) == 1) { - hi=(hi<<4)|(lo>>28); - lo=(lo<<4)|(n&0xf); - } - - PrintToScrollback("Emulating tag with ID %x%16x", hi, lo); - - UsbCommand c={CMD_HID_SIM_TAG, {hi, lo, 0}}; - SendCommand(&c); -} - -static void CmdReadmem(char *str) -{ - UsbCommand c={CMD_READ_MEM, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdVersion(char *str) -{ - UsbCommand c={CMD_VERSION}; - SendCommand(&c); -} - -static void CmdLcdReset(char *str) -{ - UsbCommand c={CMD_LCD_RESET, {strtol(str, NULL, 0), 0, 0}}; - SendCommand(&c); -} - -static void CmdLcd(char *str) -{ - int i, j; - UsbCommand c={CMD_LCD}; - sscanf(str, "%x %d", &i, &j); - while (j--) { - c.arg[0] = i&0x1ff; - SendCommand(&c); - } -} - -/* - * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below - * 600kHz. - */ -static void CmdSetDivisor(char *str) -{ - UsbCommand c={CMD_SET_LF_DIVISOR, {strtol(str, NULL, 0), 0, 0}}; - if (( c.arg[0]<0) || (c.arg[0]>255)) { - PrintToScrollback("divisor must be between 19 and 255"); - } else { - SendCommand(&c); - PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.arg[0]+1)); - } -} - -static void CmdSetMux(char *str) -{ - UsbCommand c={CMD_SET_ADC_MUX}; - if(strcmp(str, "lopkd") == 0) { - c.arg[0] = 0; - } else if(strcmp(str, "loraw") == 0) { - c.arg[0] = 1; - } else if(strcmp(str, "hipkd") == 0) { - c.arg[0] = 2; - } else if(strcmp(str, "hiraw") == 0) { - c.arg[0] = 3; - } - SendCommand(&c); -} - -typedef void HandlerFunction(char *cmdline); - -/* in alphabetic order */ -static struct { - char *name; - HandlerFunction *handler; - int offline; // 1 if the command can be used when in offline mode - char *docString; -} CommandTable[] = { -/* plot window / data buffer manipulation */ - {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, - {"load", CmdLoad, 1, " -- Load trace (to graph window"}, - {"save", CmdSave, 1, " -- Save trace (from graph window)"}, - {"amp", CmdAmp, 1, "Amplify peaks"}, - {"autocorr", CmdAutoCorr, 1, " -- Autocorrelation over window"}, - {"dec", CmdDec, 1, "Decimate samples"}, - {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, - {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, - {"norm", CmdNorm, 1, "Normalize max/min to +/-500"}, - {"plot", CmdPlot, 1, "Show graph window"}, - {"hide", CmdHide, 1, "Hide graph window"}, - {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, - {"threshold", CmdThreshold, 1, "Maximize/minimize every value in the graph window depending on threshold"}, - {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, - {"scale", CmdScale, 1, " -- Set cursor display scale"}, - {"bitstream", Cmdbitstream, 1, "[clock rate] -- Convert waveform into a bitstream"}, - {"detectclock", Cmddetectclockrate, 1, "Detect clock rate"}, - {"exit", CmdQuit, 1, "Exit program"}, - {"quit", CmdQuit, 1, "Exit program"}, - -/* low-level hardware control */ - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"hitune", CmdHiTune, 0, "Continuously measure HF antenna tuning"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"}, - {"lcd", CmdLcd, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLcdReset, 0, "Hardware reset LCD"}, - -/* data transfer functions */ - - {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, - {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, - {"higet", CmdHi14read_sim, 0, " -- Get samples HF, 'analog'"}, - {"hisamples", CmdHisamples, 0, "Get raw samples for HF tag"}, - {"hisampless", CmdHisampless, 0, " -- Get signed raw samples, HF tag"}, - {"hisamplest", CmdHi14readt, 0, "Get samples HF, for testing"}, - {"losamples", CmdLosamples, 0, "[128 - 16000] -- Get raw samples for LF tag"}, - {"detectreader", CmdDetectReader, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - -/* (de-)modulation */ - - {"askdemod", Cmdaskdemod, 1, "<0|1> -- Attempt to demodulate simple ASK tags"}, - {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, - {"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"}, - {"hi14bdemod", CmdHi14bdemod, 1, "Demodulate ISO14443 Type B from tag"}, - {"hi15demod", CmdHi15demod, 1, "Demodulate ISO15693 from tag"}, - {"hiddemod", CmdHiddemod, 1, "Demodulate HID Prox Card II (not optimal)"}, - {"hidfskdemod", CmdHIDdemodFSK, 0, "Realtime HID FSK demodulator"}, - {"indalademod", CmdIndalademod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, - {"mandemod", Cmdmanchesterdemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"}, - {"manmod", Cmdmanchestermod, 1, "[clock rate] -- Manchester modulate a binary stream"}, - {"tidemod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag"}, - {"vchdemod", CmdVchdemod, 1, "['clone'] -- Demodulate samples for VeriChip"}, - -/* simulation */ - {"em410xsim", CmdEM410xsim, 1, " -- Simulate EM410x tag"}, - {"hi14sim", CmdHi14sim, 0, "Fake ISO 14443 tag"}, - {"hi14asim", CmdHi14asim, 0, " -- Fake ISO 14443a tag"}, - {"hi15sim", CmdHi15tag, 0, "Fake an ISO15693 tag"}, - {"hidsimtag", CmdHIDsimTAG, 0, " -- HID tag simulator"}, - {"hisimlisten", CmdHisimlisten, 0, "Get HF samples as fake tag"}, - {"losim", CmdLosim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, - {"losimman", CmdLosimManchester, 0, " [GAP] Simulate arbitrary Manchester LF tag"}, - {"losimbidir", CmdLosimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, - -/* card reading functions */ - {"em410xread", CmdEM410xread, 1, "[clock rate] -- Extract ID from EM410x tag"}, - {"em410xwatch", CmdEM410xwatch, 0, "Watches for EM410x tags"}, - {"em4x50read", CmdEM4x50read, 1, "Extract data from EM4x50 tag"}, - {"hi14alist", CmdHi14alist, 0, "List ISO 14443a history"}, - {"hi14amifare", CmdHi14amifare, 0, "Read out sector 0 parity error messages"}, - {"hi14areader", CmdHi14areader, 0, "Act like an ISO14443 Type A reader"}, - {"hi14asnoop", CmdHi14asnoop, 0, "Eavesdrop ISO 14443 Type A"}, - {"hi14list", CmdHi14list, 0, "List ISO 14443 history"}, - {"hi14read", CmdHi14read, 0, "Read HF tag (ISO 14443)"}, - {"hi14snoop", CmdHi14snoop, 0, "Eavesdrop ISO 14443"}, - {"hi15read", CmdHi15read, 0, "Read HF tag (ISO 15693)"}, - {"hi15reader", CmdHi15reader, 0, "Act like an ISO15693 reader"}, - {"legicrfread", CmdLegicRfRead, 0, "Start the LEGIC RF reader"}, - {"locomread", CmdLoCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, - {"loread", CmdLoread, 0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"}, - {"sri512read", CmdSri512read, 0, " -- Read contents of a SRI512 tag"}, - {"srix4kread", CmdSrix4kread, 0, " -- Read contents of a SRIX4K tag"}, - {"tiread", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"}, - {"tiwrite", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"}, -}; - -static struct { - char *name; - char *args; - char *argshelp; - char *description; - } CommandExtendedHelp[]= { - {"detectreader","'l'|'h'","'l' specifies LF antenna scan only, 'h' specifies HF antenna scan only.","Monitor antenna for changes in voltage. Output is in three fields: CHANGED, CURRENT, PERIOD,\nwhere CHANGED is the value just changed from, CURRENT is the current value and PERIOD is the\nnumber of program loops since the last change.\n\nThe RED LED indicates LF field detected, and the GREEN LED indicates HF field detected."}, - {"tune","","","Drive LF antenna at all divisor range values (19 - 255) and store the results in the output\nbuffer. Issuing 'losamples' and then 'plot' commands will display the resulting peak. 12MHz\ndivided by the peak's position plus one gives the antenna's resonant frequency. For convenience,\nthis value is also printed out by the command."}, - }; - -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever the user types a command and -// then presses Enter, which the full command line that they typed. -//----------------------------------------------------------------------------- -void CommandReceived(char *cmd) -{ - int i; - char line[512]; - - PrintToScrollback("> %s", cmd); - - if(strcmp(cmd, "help") == 0 || strncmp(cmd,"help ",strlen("help ")) == 0) { - // check if we're doing extended help - if(strlen(cmd) > strlen("help ")) { - cmd += strlen("help "); - for(i = 0; i < sizeof(CommandExtendedHelp) / sizeof(CommandExtendedHelp[0]); i++) { - if(strcmp(CommandExtendedHelp[i].name,cmd) == 0) { - PrintToScrollback("\nExtended help for '%s':\n", cmd); - PrintToScrollback("Args: %s\t- %s\n",CommandExtendedHelp[i].args,CommandExtendedHelp[i].argshelp); - PrintToScrollback(CommandExtendedHelp[i].description); - PrintToScrollback(""); - return; - } - } - PrintToScrollback("No extended help available for '%s'", cmd); - return; - } - if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)"); - PrintToScrollback("\r\nAvailable commands:"); - for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) { - if (offline && (CommandTable[i].offline==0)) continue; - memset(line, ' ', sizeof(line)); - strcpy(line+2, CommandTable[i].name); - line[strlen(line)] = ' '; - sprintf(line+15, " -- %s", CommandTable[i].docString); - PrintToScrollback("%s", line); - } - PrintToScrollback(""); - PrintToScrollback("'help ' for extended help on that command\n"); - return; - } - - for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) { - char *name = CommandTable[i].name; - if(memcmp(cmd, name, strlen(name))==0 && - (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0')) - { - cmd += strlen(name); - while(*cmd == ' ') { - cmd++; - } - if (offline && (CommandTable[i].offline==0)) { - PrintToScrollback("Offline mode, cannot use this command."); - return; - } - (CommandTable[i].handler)(cmd); - return; - } - } - PrintToScrollback(">> bad command '%s'", cmd); -} - -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever we received a packet over USB -// that we weren't necessarily expecting, for example a debug print. -//----------------------------------------------------------------------------- -void UsbCommandReceived(UsbCommand *c) -{ -// printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command); -/* If we recognize a response, return to avoid further processing */ - switch(c->cmd) { - case CMD_DEBUG_PRINT_STRING: { - char s[100]; - if(c->arg[0] > 70 || c->arg[0] < 0) { - c->arg[0] = 0; - } - memcpy(s, c->d.asBytes, c->arg[0]); - s[c->arg[0]] = '\0'; - PrintToScrollback("#db# %s", s); - return; - } - - case CMD_DEBUG_PRINT_INTEGERS: - PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->arg[0], c->arg[1], c->arg[2]); - return; - - case CMD_MEASURED_ANTENNA_TUNING: { - int peakv, peakf; - int vLf125, vLf134, vHf; - vLf125 = c->arg[0] & 0xffff; - vLf134 = c->arg[0] >> 16; - vHf = c->arg[1] & 0xffff;; - peakf = c->arg[2] & 0xffff; - peakv = c->arg[2] >> 16; - PrintToScrollback(""); - PrintToScrollback(""); - PrintToScrollback("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0); - PrintToScrollback("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0); - PrintToScrollback("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1)); - PrintToScrollback("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0); - if (peakv<2000) - PrintToScrollback("# Your LF antenna is unusable."); - else if (peakv<10000) - PrintToScrollback("# Your LF antenna is marginal."); - if (vHf<2000) - PrintToScrollback("# Your HF antenna is unusable."); - else if (vHf<5000) - PrintToScrollback("# Your HF antenna is marginal."); - return; - } - default: - break; - } - /* Maybe it's a response: */ - switch(current_command) { - case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: - if (c->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) goto unexpected_response; - int i; - for(i=0; i<48; i++) sample_buf[i] = c->d.asBytes[i]; - received_command = c->cmd; - return; - case CMD_DOWNLOADED_SIM_SAMPLES_125K: - if (c->cmd != CMD_ACK) goto unexpected_response; - // got ACK - received_command = c->cmd; - return; - default: - unexpected_response: - PrintToScrollback("unrecognized command %08x\n", c->cmd); - break; - } -} diff --git a/client/data.c b/client/data.c new file mode 100644 index 00000000..1fc7408f --- /dev/null +++ b/client/data.c @@ -0,0 +1,25 @@ +#include +#include +#include "data.h" +#include "ui.h" +#include "proxusb.h" +#include "cmdmain.h" + +uint8_t sample_buf[SAMPLE_BUFFER_SIZE]; + +void GetFromBigBuf(uint8_t *dest, int bytes) +{ + int n = bytes/4; + + if (n % 48 != 0) { + PrintAndLog("bad len in GetFromBigBuf"); + return; + } + + for (int i = 0; i < n; i += 12) { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}}; + SendCommand(&c); + WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + memcpy(dest+(i*4), sample_buf, 48); + } +} diff --git a/client/data.h b/client/data.h new file mode 100644 index 00000000..e001482d --- /dev/null +++ b/client/data.h @@ -0,0 +1,13 @@ +#ifndef DATA_H__ +#define DATA_H__ + +#include + +#define SAMPLE_BUFFER_SIZE 64 + +extern uint8_t sample_buf[SAMPLE_BUFFER_SIZE]; +#define arraylen(x) (sizeof(x)/sizeof((x)[0])) + +void GetFromBigBuf(uint8_t *dest, int bytes); + +#endif diff --git a/client/flash.c b/client/flash.c index 61d5cf75..40c38439 100644 --- a/client/flash.c +++ b/client/flash.c @@ -1,26 +1,14 @@ #ifdef WIN32 #include #include -#include #define bzero(b,len) (memset((b), '\0', (len)), (void) 0) BOOL UsbConnect(void); #else -#include +#include #endif + #include -#include -#include -#include -#include -#include #include -#include -#include - -#include "prox.h" -#ifndef WIN32 -#include "proxmark3.h" -#endif #include "flash.h" #include "elf.h" @@ -30,269 +18,268 @@ static bool AllWritten; #define PHYSICAL_FLASH_START 0x100000 #define PHYSICAL_FLASH_END 0x200000 -void WaitForAck(void) { - UsbCommand ack; - ReceiveCommand(&ack); - if(ack.cmd != CMD_ACK) { - printf("bad ACK\n"); - exit(-1); - } +void WaitForAck(void) +{ + UsbCommand ack; + ReceiveCommand(&ack); + if (ack.cmd != CMD_ACK) { + printf("bad ACK\n"); + exit(-1); + } } struct partition partitions[] = { - {0x100000, 0x102000, 1, "bootrom"}, - {0x102000, 0x110000, 0, "fpga"}, - {0x110000, 0x140000, 0, "os"}, - {0, 0, 0, NULL}, + {0x100000, 0x102000, 1, "bootrom"}, + {0x102000, 0x110000, 0, "fpga"}, + {0x110000, 0x140000, 0, "os"}, + {0, 0, 0, NULL}, }; void WriteBlock(unsigned int block_start, unsigned int len, unsigned char *buf) { - unsigned char temp_buf[256]; - if (block_start & 0xFF) { - printf("moving stuff forward by %d bytes\n", block_start & 0xFF); - memset(temp_buf, 0xFF, block_start & 0xFF); - memcpy(temp_buf + (block_start & 0xFF), buf, len - (block_start & 0xFF)); - block_start &= ~0xFF; - } else { - memcpy(temp_buf, buf, len); - } - - UsbCommand c = {CMD_SETUP_WRITE}; - - int i; - for(i = 0; i < 240; i += 48) { - memcpy(c.d.asBytes, temp_buf+i, 48); - c.arg[0] = (i/4); - SendCommand(&c); - WaitForAck(); - } - - c.cmd = CMD_FINISH_WRITE; - c.arg[0] = block_start; - -// printf("writing block %08x\r", c.arg[0]); - memcpy(c.d.asBytes, temp_buf+240, 16); - SendCommand(&c); - WaitForAck(); - - AllWritten = true; + unsigned char temp_buf[256]; + if (block_start & 0xFF) { + printf("moving stuff forward by %d bytes\n", block_start & 0xFF); + memset(temp_buf, 0xFF, block_start & 0xFF); + memcpy(temp_buf + (block_start & 0xFF), buf, len - (block_start & 0xFF)); + block_start &= ~0xFF; + } else { + memcpy(temp_buf, buf, len); + } + + UsbCommand c = {CMD_SETUP_WRITE}; + + for (int i = 0; i < 240; i += 48) { + memcpy(c.d.asBytes, temp_buf+i, 48); + c.arg[0] = (i/4); + SendCommand(&c); + WaitForAck(); + } + + c.cmd = CMD_FINISH_WRITE; + c.arg[0] = block_start; + +// printf("writing block %08x\r", c.arg[0]); + memcpy(c.d.asBytes, temp_buf+240, 16); + SendCommand(&c); + WaitForAck(); + + AllWritten = true; } void LoadFlashFromFile(const char *file, int start_addr, int end_addr) { - FILE *f = fopen(file, "rb"); - if(!f) { - printf("couldn't open file\n"); - exit(-1); - } - - char buf[4]; - fread(buf, 1, 4, f); - if (memcmp(buf, "\x7F" "ELF", 4) == 0) { - int i; - fseek(f, 0, SEEK_SET); - Elf32_Ehdr header; - fread(&header, 1, sizeof(header), f); - int count = header.e_phnum; - printf("count=%d phoff=%x\n", count, header.e_phoff); - Elf32_Phdr phdr; - - for (i=0; i 0 && phdr.p_paddr >= PHYSICAL_FLASH_START - && (phdr.p_paddr + phdr.p_filesz) < PHYSICAL_FLASH_END) { - printf("flashing offset=%x paddr=%x size=%x\n", phdr.p_offset, phdr.p_paddr, phdr.p_filesz); - if (phdr.p_offset == 0) { - printf("skipping forward 0x2000 because of strange linker thing\n"); - phdr.p_offset += 0x2000; - phdr.p_paddr += 0x2000; - phdr.p_filesz -= 0x2000; - phdr.p_memsz -= 0x2000; - } - - fseek(f, phdr.p_offset, SEEK_SET); - ExpectedAddr = phdr.p_paddr; - while (ExpectedAddr < (phdr.p_paddr + phdr.p_filesz)) { - unsigned int bytes_to_read = phdr.p_paddr + phdr.p_filesz - ExpectedAddr; - if (bytes_to_read > 256) - bytes_to_read=256; - else - memset(QueuedToSend, 0xFF, 256); - fread(QueuedToSend, 1, bytes_to_read, f); - printf("WriteBlock(%x, %d, %02x %02x %02x %02x %02x %02x %02x %02x ... %02x %02x %02x %02x %02x %02x %02x %02x)\n", ExpectedAddr, bytes_to_read, - QueuedToSend[0], QueuedToSend[1], QueuedToSend[2], QueuedToSend[3], - QueuedToSend[4], QueuedToSend[5], QueuedToSend[6], QueuedToSend[7], - QueuedToSend[248], QueuedToSend[249], QueuedToSend[250], QueuedToSend[251], - QueuedToSend[252], QueuedToSend[253], QueuedToSend[254], QueuedToSend[255]); - WriteBlock(ExpectedAddr, 256, QueuedToSend); - ExpectedAddr += bytes_to_read; - } - } + FILE *f = fopen(file, "rb"); + if (!f) { + printf("couldn't open file\n"); + exit(-1); + } + + char buf[4]; + fread(buf, 1, 4, f); + if (memcmp(buf, "\x7F" "ELF", 4) == 0) { + fseek(f, 0, SEEK_SET); + Elf32_Ehdr header; + fread(&header, 1, sizeof(header), f); + int count = header.e_phnum; + printf("count=%d phoff=%x\n", count, header.e_phoff); + Elf32_Phdr phdr; + + for (int i = 0; i < header.e_phnum; ++i) { + fseek(f, header.e_phoff + i * sizeof(Elf32_Phdr), SEEK_SET); + fread(&phdr, 1, sizeof(phdr), f); + printf("type=%d offset=%x paddr=%x vaddr=%x filesize=%x memsize=%x flags=%x align=%x\n", + phdr.p_type, phdr.p_offset, phdr.p_paddr, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz, phdr.p_flags, phdr.p_align); + if (phdr.p_type == PT_LOAD && phdr.p_filesz > 0 && phdr.p_paddr >= PHYSICAL_FLASH_START + && (phdr.p_paddr + phdr.p_filesz) < PHYSICAL_FLASH_END) { + printf("flashing offset=%x paddr=%x size=%x\n", phdr.p_offset, phdr.p_paddr, phdr.p_filesz); + if (phdr.p_offset == 0) { + printf("skipping forward 0x2000 because of strange linker thing\n"); + phdr.p_offset += 0x2000; + phdr.p_paddr += 0x2000; + phdr.p_filesz -= 0x2000; + phdr.p_memsz -= 0x2000; } - fclose(f); - printf("\ndone.\n"); - return; - } else printf("Bad file format\n"); + fseek(f, phdr.p_offset, SEEK_SET); + ExpectedAddr = phdr.p_paddr; + while (ExpectedAddr < (phdr.p_paddr + phdr.p_filesz)) { + unsigned int bytes_to_read = phdr.p_paddr + phdr.p_filesz - ExpectedAddr; + if (bytes_to_read > 256) + bytes_to_read=256; + else + memset(QueuedToSend, 0xFF, 256); + fread(QueuedToSend, 1, bytes_to_read, f); + printf("WriteBlock(%x, %d, %02x %02x %02x %02x %02x %02x %02x %02x ... %02x %02x %02x %02x %02x %02x %02x %02x)\n", ExpectedAddr, bytes_to_read, + QueuedToSend[0], QueuedToSend[1], QueuedToSend[2], QueuedToSend[3], + QueuedToSend[4], QueuedToSend[5], QueuedToSend[6], QueuedToSend[7], + QueuedToSend[248], QueuedToSend[249], QueuedToSend[250], QueuedToSend[251], + QueuedToSend[252], QueuedToSend[253], QueuedToSend[254], QueuedToSend[255]); + WriteBlock(ExpectedAddr, 256, QueuedToSend); + ExpectedAddr += bytes_to_read; + } + } + } + + fclose(f); + printf("\ndone.\n"); + return; + } else printf("Bad file format\n"); } int PrepareFlash(struct partition *p, const char *filename, unsigned int state) { - if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { - UsbCommand c = {CMD_START_FLASH, {p->start, p->end, 0}}; - - /* Only send magic when flashing bootrom */ - if(p->precious) - c.arg[2] = START_FLASH_MAGIC; - else - c.arg[2] = 0; - - SendCommand(&c); - WaitForAck(); - } else { - fprintf(stderr, "Warning: Your bootloader does not understand the new START_FLASH command\n"); - fprintf(stderr, " It is recommended that you update your bootloader\n\n"); - exit(0); - } - - LoadFlashFromFile(filename, p->start, p->end); - return 1; + if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { + UsbCommand c = {CMD_START_FLASH, {p->start, p->end, 0}}; + + /* Only send magic when flashing bootrom */ + if (p->precious) + c.arg[2] = START_FLASH_MAGIC; + else + c.arg[2] = 0; + + SendCommand(&c); + WaitForAck(); + } else { + fprintf(stderr, "Warning: Your bootloader does not understand the new START_FLASH command\n"); + fprintf(stderr, " It is recommended that you update your bootloader\n\n"); + exit(0); + } + + LoadFlashFromFile(filename, p->start, p->end); + return 1; } unsigned int GetProxmarkState(void) { - unsigned int state = 0; - - UsbCommand c; - c.cmd = CMD_DEVICE_INFO; - SendCommand(&c); - - UsbCommand resp; - ReceiveCommand(&resp); - /* Three cases: - * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK - * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command" - * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags - */ - - switch(resp.cmd) { - case CMD_ACK: - state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM; - break; - case CMD_DEBUG_PRINT_STRING: - state = DEVICE_INFO_FLAG_CURRENT_MODE_OS; - break; - case CMD_DEVICE_INFO: - state = resp.arg[0]; - break; - default: - fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); - exit(-1); - break; - } - - return state; + unsigned int state = 0; + + UsbCommand c; + c.cmd = CMD_DEVICE_INFO; + SendCommand(&c); + + UsbCommand resp; + ReceiveCommand(&resp); + /* Three cases: + * 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK + * 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command" + * 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags + */ + + switch (resp.cmd) { + case CMD_ACK: + state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM; + break; + case CMD_DEBUG_PRINT_STRING: + state = DEVICE_INFO_FLAG_CURRENT_MODE_OS; + break; + case CMD_DEVICE_INFO: + state = resp.arg[0]; + break; + default: + fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); + exit(-1); + break; + } + + return state; } unsigned int EnterFlashState(void) { - unsigned int state = GetProxmarkState(); - - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) { - /* Already in flash state, we're done. */ - return state; - } - - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { - fprintf(stderr,"Entering flash-mode...\n"); - UsbCommand c; - bzero(&c, sizeof(c)); - - if( (state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) ) { - /* New style handover: Send CMD_START_FLASH, which will reset the board and - * enter the bootrom on the next boot. - */ - c.cmd = CMD_START_FLASH; - SendCommand(&c); - fprintf(stderr,"(You don't have to do anything. Press and release the button only if you want to abort)\n"); - fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); - } else { - /* Old style handover: Ask the user to press the button, then reset the board */ - c.cmd = CMD_HARDWARE_RESET; - SendCommand(&c); - fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); - fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); - } + unsigned int state = GetProxmarkState(); + + if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) { + /* Already in flash state, we're done. */ + return state; + } + + if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { + fprintf(stderr,"Entering flash-mode...\n"); + UsbCommand c; + bzero(&c, sizeof(c)); + + if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT)) { + /* New style handover: Send CMD_START_FLASH, which will reset the board and + * enter the bootrom on the next boot. + */ + c.cmd = CMD_START_FLASH; + SendCommand(&c); + fprintf(stderr,"(You don't have to do anything. Press and release the button only if you want to abort)\n"); + fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); + } else { + /* Old style handover: Ask the user to press the button, then reset the board */ + c.cmd = CMD_HARDWARE_RESET; + SendCommand(&c); + fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); + fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); + } #ifdef WIN32 - Sleep(1000); - while(!UsbConnect()) { Sleep(1000); } + Sleep(1000); + while (!UsbConnect()) { Sleep(1000); } #else - CloseProxmark(); - sleep(1); + CloseProxmark(); + sleep(1); - while(!(devh=OpenProxmark(0))) { sleep(1); } + while (!OpenProxmark(0)) { sleep(1); } #endif - fprintf(stderr,"Found.\n"); + fprintf(stderr,"Found.\n"); + + return GetProxmarkState(); + } - return GetProxmarkState(); - } - - return 0; + return 0; } /* On first call, have *offset = -1, *length = 0; */ int find_next_area(const char *str, int *offset, int *length) { - if(*str == '\0') return 0; - if((*offset >= 0) && str[*offset + *length] == '\0') return 0; - *offset += 1 + *length; - - char *next_comma = strchr(str + *offset, ','); - if(next_comma == NULL) { - *length = strlen(str) - *offset; - } else { - *length = next_comma-(str+*offset); - } - return 1; + if (*str == '\0') return 0; + if ((*offset >= 0) && str[*offset + *length] == '\0') return 0; + *offset += 1 + *length; + + char *next_comma = strchr(str + *offset, ','); + if (next_comma == NULL) { + *length = strlen(str) - *offset; + } else { + *length = next_comma-(str+*offset); + } + return 1; } -void do_flash(char **argv) { - unsigned int state = EnterFlashState(); - - if (!(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM)) { - fprintf(stderr, "Proxmark would not enter flash state, abort\n"); - exit(-1); - } - - int offset=-1, length=0; - int current_area = 0; - while(find_next_area(argv[1], &offset, &length)) { - int i; - struct partition *p = NULL; - for (i=0; iname, argv[2+current_area]); - PrepareFlash(p, argv[2+current_area], state); - } - current_area++; - } +void do_flash(char **argv) +{ + unsigned int state = EnterFlashState(); + + if (!(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM)) { + fprintf(stderr, "Proxmark would not enter flash state, abort\n"); + exit(-1); + } + + int offset=-1, length=0; + int current_area = 0; + while (find_next_area(argv[1], &offset, &length)) { + struct partition *p = NULL; + for (int i = 0; iname, argv[2+current_area]); + PrepareFlash(p, argv[2+current_area], state); + } + current_area++; + } } diff --git a/client/flash.h b/client/flash.h index c86602ff..ab4fca96 100644 --- a/client/flash.h +++ b/client/flash.h @@ -2,10 +2,10 @@ #define __FLASH_H__ struct partition { - int start; - int end; - int precious; - const char *name; + int start; + int end; + int precious; + const char *name; }; void FlushPrevious(int translate); diff --git a/client/flasher.c b/client/flasher.c index a425023d..3af52f83 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -1,16 +1,5 @@ -#include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "proxmark3.h" +#include "proxusb.h" #include "flash.h" unsigned int current_command = CMD_UNKNOWN; @@ -19,49 +8,49 @@ extern struct partition partitions[]; static void usage(char **argv) { - int i; - fprintf(stderr, "Usage: %s areas image [image [image]]\n", argv[0]); - fprintf(stderr, " areas is a comma-separated list of areas to flash, with no spaces\n"); - fprintf(stderr, " Known areas are:"); + fprintf(stderr, "Usage: %s areas image [image [image]]\n", argv[0]); + fprintf(stderr, " areas is a comma-separated list of areas to flash, with no spaces\n"); + fprintf(stderr, " Known areas are:"); - for(i=0; partitions[i].name != NULL; i++) { - fprintf(stderr, " %s", partitions[i].name); - } + for (int i = 0; partitions[i].name != NULL; ++i) { + fprintf(stderr, " %s", partitions[i].name); + } - fprintf(stderr, "\n"); - fprintf(stderr, " image is the path to the corresponding image\n\n"); - fprintf(stderr, "Example: %s os,fpga path/to/osimage.elf path/to/fpgaimage.elf\n", argv[0]); + fprintf(stderr, "\n"); + fprintf(stderr, " image is the path to the corresponding image\n\n"); + fprintf(stderr, "Example: %s os,fpga path/to/osimage.elf path/to/fpgaimage.elf\n", argv[0]); } -int main(int argc, char **argv) { - if(argc < 2) { - usage(argv); - exit(-1); - } - - /* Count area arguments */ - int areas = 0, offset=-1, length=0; - while(find_next_area(argv[1], &offset, &length)) areas++; - - if(areas != argc - 2) { - usage(argv); - exit(-1); - } - - usb_init(); +int main(int argc, char **argv) +{ + if (argc < 2) { + usage(argv); + exit(-1); + } + + /* Count area arguments */ + int areas = 0, offset=-1, length=0; + while (find_next_area(argv[1], &offset, &length)) areas++; + + if (areas != argc - 2) { + usage(argv); + exit(-1); + } + + usb_init(); + + fprintf(stderr,"Waiting for Proxmark to appear on USB... "); + while (!OpenProxmark(0)) { sleep(1); } + fprintf(stderr,"Found.\n"); + + do_flash(argv); - fprintf(stderr,"Waiting for Proxmark to appear on USB... "); - while(!(devh=OpenProxmark(0))) { sleep(1); } - fprintf(stderr,"Found.\n"); - - do_flash(argv); - - UsbCommand c = {CMD_HARDWARE_RESET}; - SendCommand(&c); + UsbCommand c = {CMD_HARDWARE_RESET}; + SendCommand(&c); - CloseProxmark(); + CloseProxmark(); - fprintf(stderr,"Have a nice day!\n"); + fprintf(stderr,"Have a nice day!\n"); - return 0; + return 0; } diff --git a/client/graph.c b/client/graph.c new file mode 100644 index 00000000..4a966676 --- /dev/null +++ b/client/graph.c @@ -0,0 +1,85 @@ +#include +#include +#include "ui.h" +#include "graph.h" + +int GraphBuffer[MAX_GRAPH_TRACE_LEN]; +int GraphTraceLen; + +/* write a bit to the graph */ +void AppendGraph(int redraw, int clock, int bit) +{ + int i; + + for (i = 0; i < (int)(clock / 2); ++i) + GraphBuffer[GraphTraceLen++] = bit ^ 1; + + for (i = (int)(clock / 2); i < clock; ++i) + GraphBuffer[GraphTraceLen++] = bit; + + if (redraw) + RepaintGraphWindow(); +} + +/* clear out our graph window */ +int ClearGraph(int redraw) +{ + int gtl = GraphTraceLen; + GraphTraceLen = 0; + + if (redraw) + RepaintGraphWindow(); + + return gtl; +} + +/* + * Detect clock rate + */ +int DetectClock(int peak) +{ + int i; + int clock = 0xFFFF; + int lastpeak = 0; + + /* Detect peak if we don't have one */ + if (!peak) + for (i = 0; i < GraphTraceLen; ++i) + if (GraphBuffer[i] > peak) + peak = GraphBuffer[i]; + + for (i = 1; i < GraphTraceLen; ++i) + { + /* If this is the beginning of a peak */ + if (GraphBuffer[i - 1] != GraphBuffer[i] && GraphBuffer[i] == peak) + { + /* Find lowest difference between peaks */ + if (lastpeak && i - lastpeak < clock) + clock = i - lastpeak; + lastpeak = i; + } + } + + return clock; +} + +/* Get or auto-detect clock rate */ +int GetClock(const char *str, int peak, int verbose) +{ + int clock; + + sscanf(str, "%i", &clock); + if (!strcmp(str, "")) + clock = 0; + + /* Auto-detect clock */ + if (!clock) + { + clock = DetectClock(peak); + /* Only print this message if we're not looping something */ + if (!verbose) + PrintAndLog("Auto-detected clock rate: %d", clock); + } + + return clock; +} diff --git a/client/graph.h b/client/graph.h new file mode 100644 index 00000000..67041430 --- /dev/null +++ b/client/graph.h @@ -0,0 +1,13 @@ +#ifndef GRAPH_H__ +#define GRAPH_H__ + +void AppendGraph(int redraw, int clock, int bit); +int ClearGraph(int redraw); +int DetectClock(int peak); +int GetClock(const char *str, int peak, int verbose); + +#define MAX_GRAPH_TRACE_LEN (1024*128) +extern int GraphBuffer[MAX_GRAPH_TRACE_LEN]; +extern int GraphTraceLen; + +#endif diff --git a/client/gui.c b/client/gui.c deleted file mode 100644 index b8761d6d..00000000 --- a/client/gui.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include - -#include "proxgui.h" -#include "prox.h" - -int GraphBuffer[MAX_GRAPH_TRACE_LEN]; -int GraphTraceLen; -double CursorScaleFactor; -int PlotGridX, PlotGridY; -int CommandFinished; -int offline; - -static char *logfilename = "proxmark3.log"; - -void PrintToScrollback(char *fmt, ...) { - va_list argptr, argptr2; - static FILE *logfile = NULL; - static int logging=1; - - if (logging && !logfile) { - logfile=fopen(logfilename, "a"); - if (!logfile) { - fprintf(stderr, "Can't open logfile, logging disabled!\n"); - logging=0; - } - } - - va_start(argptr, fmt); - va_copy(argptr2, argptr); - vprintf(fmt, argptr); - va_end(argptr); - printf("\n"); - if (logging && logfile) { -#if 0 - char zeit[25]; - time_t jetzt_t; - struct tm *jetzt; - - jetzt_t = time(NULL); - jetzt = localtime(&jetzt_t); - strftime(zeit, 25, "%b %e %T", jetzt); - - fprintf(logfile,"%s ", zeit); -#endif - vfprintf(logfile, fmt, argptr2); - fprintf(logfile,"\n"); - fflush(logfile); - } - va_end(argptr2); -} - -void setlogfilename(char *fn) -{ - logfilename = fn; -} diff --git a/client/prox.h b/client/prox.h deleted file mode 100644 index 4742ba9a..00000000 --- a/client/prox.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __PROX_H -#define __PROX_H -#ifdef _MSC_VER -typedef DWORD uint32_t; -typedef BYTE uint8_t; -typedef WORD uint16_t; -#define bool BOOL -#else -#include -#include -#endif -#include "../include/usb_cmd.h" - -// prox.cpp -void ReceiveCommand(UsbCommand *c); -bool ReceiveCommandPoll(UsbCommand *c); -void SendCommand(UsbCommand *c); -void WaitForAck(void); -void wait_for_response(uint32_t command_type); - -// gui.cpp -void ShowGui(void); -void HideGraphWindow(void); -void ShowGraphWindow(void); -void RepaintGraphWindow(void); -void PrintToScrollback(char *fmt, ...); -#define MAX_GRAPH_TRACE_LEN (1024*128) -extern int GraphBuffer[MAX_GRAPH_TRACE_LEN]; -extern int GraphTraceLen; -extern double CursorScaleFactor; -extern int PlotGridX, PlotGridY; -extern int CommandFinished; -extern int offline; - -// command.cpp -static void CmdBuffClear(char *str); -static void GetFromBigBuf(uint8_t *dest, int bytes); -static void CmdReset(char *str); -static void CmdQuit(char *str); -static void CmdEM410xread(char *str); -static void CmdEM410xwatch(char *str); -static void ChkBitstream(char *str); -int GetClock(char *str, int peak); -static void CmdHIDdemodFSK(char *str); -static void Cmdmanchestermod(char *str); -static void CmdTune(char *str); -static void CmdHiTune(char *str); -static void CmdHi15read(char *str); -static void CmdHi14read(char *str); -static void CmdSri512read(char *str); -static void CmdHi14areader(char *str); -static void CmdHi15reader(char *str); -static void CmdHi15tag(char *str); -static void CmdHi14read_sim(char *str); -static void CmdHi14readt(char *str); -static void CmdHisimlisten(char *str); -static void CmdReadmem(char *str); -static void CmdHi14sim(char *str); -static void CmdHi14asim(char *str); -static void CmdHi14snoop(char *str); -static void CmdHi14asnoop(char *str); -static void CmdFPGAOff(char *str); -int CmdClearGraph(int redraw); -static void CmdAppendGraph(int redraw, int clock, int bit); -static void CmdEM410xsim(char *str); -static void CmdLosim(char *str); -static void CmdLoCommandRead(char *str); -static void CmdLoread(char *str); -static void CmdLosamples(char *str); -static void CmdBitsamples(char *str); -static void CmdHisamples(char *str); -static int CmdHisamplest(char *str, int nrlow); -static void CmdHexsamples(char *str); -static void CmdHisampless(char *str); -static uint16_t Iso15693Crc(uint8_t *v, int n); -static void CmdHi14bdemod(char *str); -static void CmdHi14list(char *str); -static void CmdHi14alist(char *str); -static void CmdHi15demod(char *str); -static void CmdTiread(char *str); -static void CmdTibits(char *str); -static void CmdTidemod(char *cmdline); -static void CmdNorm(char *str); -static void CmdDec(char *str); -static void CmdHpf(char *str); -static void CmdZerocrossings(char *str); -static void CmdLtrim(char *str); -static void CmdAutoCorr(char *str); -static void CmdVchdemod(char *str); -static void CmdIndalademod(char *str); -static void CmdFlexdemod(char *str); -static void Cmdaskdemod(char *str); -static void Cmddetectclockrate(char *str); -int detectclock(int peak); -static void Cmdbitstream(char *str); -static void Cmdmanchesterdemod(char *str); -static void CmdHiddemod(char *str); -static void CmdPlot(char *str); -static void CmdHide(char *str); -static void CmdScale(char *str); -static void CmdSave(char *str); -static void CmdLoad(char *str); -static void CmdHIDsimTAG(char *str); -static void CmdLcdReset(char *str); -static void CmdLcd(char *str); -static void CmdTest(char *str); -static void CmdSetDivisor(char *str); -static void CmdSweepLF(char *str); -void CommandReceived(char *cmd); -void UsbCommandReceived(UsbCommand *c); - - -// cmdline.cpp -void ShowCommandline(void); -void ExecCmd(char *cmd); -//void PrintToScrollback(char *fmt, ...); - -#endif diff --git a/client/proxgui.cpp b/client/proxgui.cpp index 7e87b582..2858157c 100644 --- a/client/proxgui.cpp +++ b/client/proxgui.cpp @@ -5,54 +5,54 @@ static ProxGuiQT *gui = NULL; extern "C" void ShowGraphWindow(void) { - if (!gui) - return; - - gui->ShowGraphWindow(); + if (!gui) + return; + + gui->ShowGraphWindow(); } extern "C" void HideGraphWindow(void) { - if (!gui) - return; - - gui->HideGraphWindow(); + if (!gui) + return; + + gui->HideGraphWindow(); } extern "C" void RepaintGraphWindow(void) { - if (!gui) - return; + if (!gui) + return; - gui->RepaintGraphWindow(); + gui->RepaintGraphWindow(); } extern "C" void MainGraphics(void) { - if (!gui) - return; + if (!gui) + return; - gui->MainLoop(); + gui->MainLoop(); } extern "C" void InitGraphics(int argc, char **argv) { #ifdef Q_WS_X11 - bool useGUI = getenv("DISPLAY") != 0; + bool useGUI = getenv("DISPLAY") != 0; #else - bool useGUI = true; + bool useGUI = true; #endif - if (!useGUI) - return; + if (!useGUI) + return; - gui = new ProxGuiQT(argc, argv); + gui = new ProxGuiQT(argc, argv); } extern "C" void ExitGraphics(void) { - if (!gui) - return; - - delete gui; - gui = NULL; + if (!gui) + return; + + delete gui; + gui = NULL; } diff --git a/client/proxmark3.c b/client/proxmark3.c index 2e8ef418..830a1245 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -1,106 +1,100 @@ -#include #include -#include -#include -#include #include -#include +#include #include #include -#include - -#include "prox.h" +#include "proxusb.h" #include "proxmark3.h" #include "proxgui.h" +#include "cmdmain.h" -struct usb_receiver_arg { - int run; +struct usb_receiver_arg +{ + int run; }; -struct main_loop_arg { - int usb_present; +struct main_loop_arg +{ + int usb_present; }; -static void *usb_receiver(void *targ) { - struct usb_receiver_arg *arg = (struct usb_receiver_arg*)targ; - UsbCommand cmdbuf; - - while(arg->run) { - if (ReceiveCommandPoll(&cmdbuf)) { - int i; - - for (i=0; irun) { + if (ReceiveCommandPoll(&cmdbuf)) { + for (int i = 0; i < strlen(PROXPROMPT); i++) + putchar(0x08); + UsbCommandReceived(&cmdbuf); + printf(PROXPROMPT); + fflush(NULL); + } + } + + pthread_exit(NULL); } static void *main_loop(void *targ) { - struct main_loop_arg *arg = (struct main_loop_arg*)targ; - struct usb_receiver_arg rarg; - char *cmd = NULL; - pthread_t reader_thread; - - if (arg->usb_present == 1) { - rarg.run=1; - pthread_create(&reader_thread, NULL, &usb_receiver, &rarg); - } - - while(1) { - - cmd = readline(PROXPROMPT); - if (cmd) { - if (cmd[0] != 0x00) { - CommandReceived(cmd); - add_history(cmd); - } - free(cmd); - } else { - printf("\n"); - break; - } - } - - if (arg->usb_present == 1) { - rarg.run = 0; - pthread_join(reader_thread, NULL); - } - - ExitGraphics(); - pthread_exit(NULL); + struct main_loop_arg *arg = (struct main_loop_arg*)targ; + struct usb_receiver_arg rarg; + char *cmd = NULL; + pthread_t reader_thread; + + if (arg->usb_present == 1) { + rarg.run=1; + pthread_create(&reader_thread, NULL, &usb_receiver, &rarg); + } + + while(1) { + cmd = readline(PROXPROMPT); + if (cmd) { + if (cmd[0] != 0x00) { + CommandReceived(cmd); + add_history(cmd); + } + free(cmd); + } else { + printf("\n"); + break; + } + } + + if (arg->usb_present == 1) { + rarg.run = 0; + pthread_join(reader_thread, NULL); + } + + ExitGraphics(); + pthread_exit(NULL); } int main(int argc, char **argv) { - struct main_loop_arg marg; - pthread_t main_loop_t; - usb_init(); - - if (!(devh = OpenProxmark(1))) { - fprintf(stderr,"PROXMARK3: NOT FOUND!\n"); - marg.usb_present = 0; - offline = 1; - } else { - marg.usb_present = 1; - offline = 0; - } - - pthread_create(&main_loop_t, NULL, &main_loop, &marg); - InitGraphics(argc, argv); - - MainGraphics(); - - pthread_join(main_loop_t, NULL); - - if (marg.usb_present == 1) { - CloseProxmark(); - } - return 0; + struct main_loop_arg marg; + pthread_t main_loop_t; + usb_init(); + + if (!OpenProxmark(1)) { + fprintf(stderr,"PROXMARK3: NOT FOUND!\n"); + marg.usb_present = 0; + offline = 1; + } else { + marg.usb_present = 1; + offline = 0; + } + + pthread_create(&main_loop_t, NULL, &main_loop, &marg); + InitGraphics(argc, argv); + + MainGraphics(); + + pthread_join(main_loop_t, NULL); + + if (marg.usb_present == 1) { + CloseProxmark(); + } + return 0; } diff --git a/client/proxmark3.h b/client/proxmark3.h index 67d80841..5d55fc82 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -1,14 +1,6 @@ -#define PROXPROMPT "proxmark3> " - -#define FLASH_ADDR_OS 0x10000 -#define FLASH_ADDR_FPGA 0x2000 +#ifndef PROXMARK3_H__ +#define PROXMARK3_H__ -extern usb_dev_handle *devh; -extern unsigned char return_on_error; -extern unsigned char error_occured; - -int ReceiveCommandP(UsbCommand *c); -usb_dev_handle* OpenProxmark(int); -void CloseProxmark(void); +#define PROXPROMPT "proxmark3> " -void setlogfilename(char *fn); +#endif \ No newline at end of file diff --git a/client/proxusb.c b/client/proxusb.c new file mode 100644 index 00000000..be37fc69 --- /dev/null +++ b/client/proxusb.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "proxusb.h" +#include "proxmark3.h" +#include "usb_cmd.h" + +usb_dev_handle *devh = NULL; +static unsigned int claimed_iface = 0; +unsigned char return_on_error = 0; +unsigned char error_occured = 0; +extern unsigned int current_command; + +void SendCommand(UsbCommand *c) +{ + int ret; + +#if 0 + printf("Sending %d bytes\n", sizeof(UsbCommand)); +#endif + current_command = c->cmd; + ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000); + if (ret<0) { + error_occured = 1; + if (return_on_error) + return; + + fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n", + usb_strerror()); + + if (devh) { + usb_close(devh); + devh = NULL; + } + while(!(devh=OpenProxmark(0))) { sleep(1); } + printf(PROXPROMPT); + fflush(NULL); + + return; + } +} + +bool ReceiveCommandPoll(UsbCommand *c) +{ + int ret; + + bzero(c, sizeof(UsbCommand)); + ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500); + if (ret<0) { + if (ret != -ETIMEDOUT) { + error_occured = 1; + if (return_on_error) + return false; + + fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n", + usb_strerror(), ret); + + if (devh) { + usb_close(devh); + devh = NULL; + } + while(!(devh=OpenProxmark(0))) { sleep(1); } + printf(PROXPROMPT); + fflush(NULL); + + return false; + } + } else { + if (ret && (ret < sizeof(UsbCommand))) { + fprintf(stderr, "Read only %d instead of requested %d bytes!\n", + ret, (int)sizeof(UsbCommand)); + } + } + + return ret > 0; +} + +void ReceiveCommand(UsbCommand *c) +{ +// printf("%s()\n", __FUNCTION__); + int retval = 0; + do { + retval = ReceiveCommandPoll(c); + if (retval != 1) printf("ReceiveCommandPoll returned %d\n", retval); + } while(retval<0); +// printf("recv %x\n", c->cmd); +} + +usb_dev_handle* findProxmark(int verbose, unsigned int *iface) +{ + struct usb_bus *busses, *bus; + usb_dev_handle *handle = NULL; + + usb_find_busses(); + usb_find_devices(); + + busses = usb_get_busses(); + + for (bus = busses; bus; bus = bus->next) { + struct usb_device *dev; + + for (dev = bus->devices; dev; dev = dev->next) { + struct usb_device_descriptor *desc = &(dev->descriptor); + + if ((desc->idProduct == 0x4b8f) && (desc->idVendor == 0x9ac4)) { + handle = usb_open(dev); + if (!handle) { + if (verbose) + fprintf(stderr, "open failed: %s!\n", usb_strerror()); + return NULL; + } + *iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; + return handle; + } + + } + } + + return NULL; +} + +usb_dev_handle* OpenProxmark(int verbose) +{ + int ret; + usb_dev_handle *handle = NULL; + unsigned int iface; + +#ifndef __APPLE__ + handle = findProxmark(verbose, &iface); + if (!handle) + return NULL; + + /* Whatever... */ + usb_reset(handle); +#endif + + handle = findProxmark(verbose, &iface); + if (!handle) + return NULL; + +#ifndef __APPLE__ + /* detach kernel driver first */ + ret = usb_detach_kernel_driver_np(handle, iface); + /* don't complain if no driver attached */ + if (ret<0 && ret != -61 && verbose) + fprintf(stderr, "detach kernel driver failed: (%d) %s!\n", ret, usb_strerror()); +#endif + ret = usb_claim_interface(handle, iface); + if (ret < 0) { + if (verbose) + fprintf(stderr, "claim failed: %s!\n", usb_strerror()); + return NULL; + } + + claimed_iface = iface; + devh = handle; + return handle; +} + +void CloseProxmark(void) +{ + usb_release_interface(devh, claimed_iface); + usb_close(devh); +} diff --git a/client/proxusb.h b/client/proxusb.h new file mode 100644 index 00000000..a6e27ddf --- /dev/null +++ b/client/proxusb.h @@ -0,0 +1,27 @@ +#ifndef PROXUSB_H__ +#define PROXUSB_H__ + +#ifdef _MSC_VER +typedef DWORD uint32_t; +typedef BYTE uint8_t; +typedef WORD uint16_t; +#define bool BOOL +#else +#include +#include +#endif +#include +#include "usb_cmd.h" + +extern unsigned char return_on_error; +extern unsigned char error_occured; + +void SendCommand(UsbCommand *c); +bool ReceiveCommandPoll(UsbCommand *c); +void ReceiveCommand(UsbCommand *c); +usb_dev_handle* FindProxmark(int verbose, unsigned int *iface); +usb_dev_handle* OpenProxmark(int verbose); +usb_dev_handle* OpenProxmark(int verbose); +void CloseProxmark(void); + +#endif diff --git a/client/snooper.c b/client/snooper.c index e6d4c364..01449748 100644 --- a/client/snooper.c +++ b/client/snooper.c @@ -1,48 +1,36 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "proxmark3.h" +#include "ui.h" +#include "proxusb.h" +#include "cmdmain.h" #define HANDLE_ERROR if (error_occured) { \ - error_occured = 0;\ - break;\ + error_occured = 0;\ + break;\ } int main() { - usb_init(); - setlogfilename("snooper.log"); - - return_on_error = 1; - - while(1) { - while(!(devh=OpenProxmark(0))) { sleep(1); } - - while(1) { - UsbCommand cmdbuf; - int i; - - CommandReceived("hi14asnoop"); - HANDLE_ERROR - - ReceiveCommand(&cmdbuf); - HANDLE_ERROR - for (i=0; i<5; i++) { - ReceiveCommandPoll(&cmdbuf); - } - HANDLE_ERROR - - CommandReceived("hi14alist"); - HANDLE_ERROR - } - } - - CloseProxmark(); - return 0; + usb_init(); + SetLogFilename("snooper.log"); + + return_on_error = 1; + + while(1) { + while (!OpenProxmark(0)) { sleep(1); } + while (1) { + UsbCommand cmdbuf; + CommandReceived("hi14asnoop"); + HANDLE_ERROR; + ReceiveCommand(&cmdbuf); + HANDLE_ERROR; + for (int i = 0; i < 5; ++i) { + ReceiveCommandPoll(&cmdbuf); + } + HANDLE_ERROR; + CommandReceived("hi14alist"); + HANDLE_ERROR; + } + } + + CloseProxmark(); + return 0; } diff --git a/client/translate.h b/client/translate.h deleted file mode 100644 index 145268a0..00000000 --- a/client/translate.h +++ /dev/null @@ -1,9 +0,0 @@ -#define BYTE unsigned char -#define WORD unsigned short -#define DWORD unsigned int -#define TRUE 1 -#define FALSE 0 -#define BOOL int - -#define max(a,b) (((a)>(b))?(a):(b)) -#define min(a,b) (((a)>(b))?(b):(a)) diff --git a/client/ui.c b/client/ui.c new file mode 100644 index 00000000..9f4377c8 --- /dev/null +++ b/client/ui.c @@ -0,0 +1,54 @@ +#include +#include +#include + +#include "ui.h" + +double CursorScaleFactor; +int PlotGridX, PlotGridY; +int offline; + +static char *logfilename = "proxmark3.log"; + +void PrintAndLog(char *fmt, ...) +{ + va_list argptr, argptr2; + static FILE *logfile = NULL; + static int logging=1; + + if (logging && !logfile) { + logfile=fopen(logfilename, "a"); + if (!logfile) { + fprintf(stderr, "Can't open logfile, logging disabled!\n"); + logging=0; + } + } + + va_start(argptr, fmt); + va_copy(argptr2, argptr); + vprintf(fmt, argptr); + va_end(argptr); + printf("\n"); + if (logging && logfile) { +#if 0 + char zeit[25]; + time_t jetzt_t; + struct tm *jetzt; + + jetzt_t = time(NULL); + jetzt = localtime(&jetzt_t); + strftime(zeit, 25, "%b %e %T", jetzt); + + fprintf(logfile,"%s ", zeit); +#endif + vfprintf(logfile, fmt, argptr2); + fprintf(logfile,"\n"); + fflush(logfile); + } + va_end(argptr2); +} + +void SetLogFilename(char *fn) +{ + logfilename = fn; +} diff --git a/client/ui.h b/client/ui.h new file mode 100644 index 00000000..8d58cf35 --- /dev/null +++ b/client/ui.h @@ -0,0 +1,15 @@ +#ifndef UI_H__ +#define UI_H__ + +void ShowGui(void); +void HideGraphWindow(void); +void ShowGraphWindow(void); +void RepaintGraphWindow(void); +void PrintAndLog(char *fmt, ...); +void SetLogFilename(char *fn); + +extern double CursorScaleFactor; +extern int PlotGridX, PlotGridY; +extern int offline; + +#endif diff --git a/client/usb.c b/client/usb.c deleted file mode 100644 index e0836b82..00000000 --- a/client/usb.c +++ /dev/null @@ -1,163 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "proxmark3.h" -#include "../include/usb_cmd.h" -usb_dev_handle *devh = NULL; -static unsigned int claimed_iface = 0; -unsigned char return_on_error = 0; -unsigned char error_occured = 0; -extern unsigned int current_command; - -void SendCommand(UsbCommand *c) { - int ret; - -#if 0 - printf("Sending %d bytes\n", sizeof(UsbCommand)); -#endif - current_command = c->cmd; - ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000); - if (ret<0) { - error_occured = 1; - if (return_on_error) - return; - - fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n", - usb_strerror()); - - if (devh) { - usb_close(devh); - devh = NULL; - } - while(!(devh=OpenProxmark(0))) { sleep(1); } - printf(PROXPROMPT); - fflush(NULL); - - return; - } -} - -bool ReceiveCommandPoll(UsbCommand *c) { - int ret; - - bzero(c, sizeof(UsbCommand)); - ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500); - if (ret<0) { - if (ret != -ETIMEDOUT) { - error_occured = 1; - if (return_on_error) - return false; - - fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n", - usb_strerror(), ret); - - if (devh) { - usb_close(devh); - devh = NULL; - } - while(!(devh=OpenProxmark(0))) { sleep(1); } - printf(PROXPROMPT); - fflush(NULL); - - return false; - } - } else { - if (ret && (ret < sizeof(UsbCommand))) { - fprintf(stderr, "Read only %d instead of requested %d bytes!\n", - ret, (int)sizeof(UsbCommand)); - } - } - - return ret > 0; -} - -void ReceiveCommand(UsbCommand *c) { -// printf("%s()\n", __FUNCTION__); - int retval = 0; - do { - retval = ReceiveCommandPoll(c); - if (retval != 1) printf("ReceiveCommandPoll returned %d\n", retval); - } while(retval<0); -// printf("recv %x\n", c->cmd); -} - -usb_dev_handle* findProxmark(int verbose, unsigned int *iface) { - struct usb_bus *busses, *bus; - usb_dev_handle *handle = NULL; - - usb_find_busses(); - usb_find_devices(); - - busses = usb_get_busses(); - - for (bus = busses; bus; bus = bus->next) { - struct usb_device *dev; - - for (dev = bus->devices; dev; dev = dev->next) { - struct usb_device_descriptor *desc = &(dev->descriptor); - - if ((desc->idProduct == 0x4b8f) && (desc->idVendor == 0x9ac4)) { - handle = usb_open(dev); - if (!handle) { - if (verbose) - fprintf(stderr, "open failed: %s!\n", usb_strerror()); - return NULL; - } - - *iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; - - return handle; - } - } - } - - return NULL; -} - -usb_dev_handle* OpenProxmark(int verbose) { - int ret; - usb_dev_handle *handle = NULL; - unsigned int iface; - -#ifndef __APPLE__ - handle = findProxmark(verbose, &iface); - if (!handle) - return NULL; - - /* Whatever... */ - usb_reset(handle); -#endif - - handle = findProxmark(verbose, &iface); - if (!handle) - return NULL; - -#ifndef __APPLE__ - /* detach kernel driver first */ - ret = usb_detach_kernel_driver_np(handle, iface); - /* don't complain if no driver attached */ - if (ret<0 && ret != -61 && verbose) - fprintf(stderr, "detach kernel driver failed: (%d) %s!\n", ret, usb_strerror()); -#endif - ret = usb_claim_interface(handle, iface); - if (ret<0) { - if (verbose) - fprintf(stderr, "claim failed: %s!\n", usb_strerror()); - return NULL; - } - - claimed_iface = iface; - devh = handle; - return handle; -} - -void CloseProxmark(void) { - usb_release_interface(devh, claimed_iface); - usb_close(devh); -} diff --git a/common/Makefile.common b/common/Makefile.common index c2903a8f..c1193f9a 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -17,7 +17,7 @@ OBJCOPY = $(CROSS)objcopy OBJDIR = obj -INCLUDE = -I../include +INCLUDE = -I../include -I../common # Windows' echo echos its input verbatim, on Posix there is some # amount of shell command line parsing going on. echo "" on @@ -57,7 +57,7 @@ INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gp CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=gnu99 $(APP_CFLAGS) THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC)) -ARMOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(ARMSRC)) +ARMOBJ = $(ARMSRC:%.c=$(OBJDIR)/%.o) ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(ASMSRC)) VERSIONOBJ = $(OBJDIR)/version.o diff --git a/common/crc16.c b/common/crc16.c index c26ced8a..a5713333 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -1,7 +1,10 @@ -unsigned short update_crc16( unsigned short crc, unsigned char c ) { - unsigned short i, v, tcrc = 0; +#include "crc16.h" - v = (crc ^ c) & 0xff; +unsigned short update_crc16( unsigned short crc, unsigned char c ) +{ + unsigned short i, v, tcrc = 0; + + v = (crc ^ c) & 0xff; for (i = 0; i < 8; i++) { tcrc = ( (tcrc ^ v) & 1 ) ? ( tcrc >> 1 ) ^ 0x8408 : tcrc >> 1; v >>= 1; diff --git a/common/crc16.h b/common/crc16.h new file mode 100644 index 00000000..b7e2824c --- /dev/null +++ b/common/crc16.h @@ -0,0 +1,6 @@ +#ifndef CRC16_H__ +#define CRC16_H__ + +unsigned short update_crc16(unsigned short crc, unsigned char c); + +#endif diff --git a/common/iso14443_crc.c b/common/iso14443_crc.c deleted file mode 100644 index 555de7db..00000000 --- a/common/iso14443_crc.c +++ /dev/null @@ -1,35 +0,0 @@ -//----------------------------------------------------------------------------- -// Routines to compute the CRCs (two different flavours, just for confusion) -// required for ISO 14443, swiped directly from the spec. -//----------------------------------------------------------------------------- - -#define CRC_14443_A 0x6363 /* ITU-V.41 */ -#define CRC_14443_B 0xFFFF /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ - -static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc) -{ - ch = (ch ^ (unsigned char) ((*lpwCrc) & 0x00FF)); - ch = (ch ^ (ch << 4)); - *lpwCrc = (*lpwCrc >> 8) ^ ((unsigned short) ch << 8) ^ - ((unsigned short) ch << 3) ^ ((unsigned short) ch >> 4); - return (*lpwCrc); -} - -static void ComputeCrc14443(int CrcType, unsigned char *Data, int Length, - unsigned char *TransmitFirst, unsigned char *TransmitSecond) -{ - unsigned char chBlock; - unsigned short wCrc=CrcType; - - do { - chBlock = *Data++; - UpdateCrc14443(chBlock, &wCrc); - } while (--Length); - - if (CrcType == CRC_14443_B) - wCrc = ~wCrc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ - - *TransmitFirst = (unsigned char) (wCrc & 0xFF); - *TransmitSecond = (unsigned char) ((wCrc >> 8) & 0xFF); - return; -} diff --git a/common/iso14443crc.c b/common/iso14443crc.c new file mode 100644 index 00000000..250a4ee5 --- /dev/null +++ b/common/iso14443crc.c @@ -0,0 +1,31 @@ +#include "iso14443crc.h" + +static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc) +{ + ch = (ch ^ (unsigned char) ((*lpwCrc) & 0x00FF)); + ch = (ch ^ (ch << 4)); + *lpwCrc = (*lpwCrc >> 8) ^ ((unsigned short) ch << 8) ^ + ((unsigned short) ch << 3) ^ ((unsigned short) ch >> 4); + return (*lpwCrc); +} + +void ComputeCrc14443(int CrcType, + unsigned char *Data, int Length, + unsigned char *TransmitFirst, + unsigned char *TransmitSecond) +{ + unsigned char chBlock; + unsigned short wCrc=CrcType; + + do { + chBlock = *Data++; + UpdateCrc14443(chBlock, &wCrc); + } while (--Length); + + if (CrcType == CRC_14443_B) + wCrc = ~wCrc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ + + *TransmitFirst = (unsigned char) (wCrc & 0xFF); + *TransmitSecond = (unsigned char) ((wCrc >> 8) & 0xFF); + return; +} diff --git a/common/iso14443crc.h b/common/iso14443crc.h new file mode 100644 index 00000000..a435d09c --- /dev/null +++ b/common/iso14443crc.h @@ -0,0 +1,16 @@ +#ifndef ISO14443CRC_H__ +#define ISO14443CRC_H__ + +//----------------------------------------------------------------------------- +// Routines to compute the CRCs (two different flavours, just for confusion) +// required for ISO 14443, swiped directly from the spec. +//----------------------------------------------------------------------------- +#define CRC_14443_A 0x6363 /* ITU-V.41 */ +#define CRC_14443_B 0xFFFF /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ + +void ComputeCrc14443(int CrcType, + unsigned char *Data, int Length, + unsigned char *TransmitFirst, + unsigned char *TransmitSecond); + +#endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 71f0221c..a0c2745f 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -66,7 +66,6 @@ typedef struct { // For the 13.56 MHz tags #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM 0x0302 #define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRIX4K_TAG 0x0304 #define CMD_READER_ISO_15693 0x0310