From: bushing Date: Tue, 22 Dec 2009 12:11:15 +0000 (+0000) Subject: merge linux and windows clients into one directory... will consolidate makefiles... X-Git-Tag: v1.0.0~443 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/cd00aa3043b507ed10bf79a37b83b88741d176d7 merge linux and windows clients into one directory... will consolidate makefiles shortly --- diff --git a/client/Makefile b/client/Makefile new file mode 100644 index 00000000..113223fb --- /dev/null +++ b/client/Makefile @@ -0,0 +1,40 @@ +#COMMON_FLAGS = -m32 +LDLIBS = -L/usr/local/lib -lusb -lreadline -lpthread +LDFLAGS = $(COMMON_FLAGS) +CFLAGS = -I. -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) + +CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall +QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) + +ifneq ($(QTLDLIBS),) +QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o +CFLAGS += -DHAVE_GUI +MOC = $(shell type moc-qt4 >/dev/null 2>&1 && echo moc-qt4 || echo moc) +LINK.o = $(LINK.cpp) +else +QTGUI = guidummy.o +endif + +all: proxmark3 snooper cli flasher + +all-static: LDLIBS:=-static $(LDLIBS) +all-static: snooper cli flasher + +proxmark3: LDLIBS+=$(QTLDLIBS) +proxmark3: proxmark3.o gui.o command.o usb.o $(QTGUI) + +command.o: command.cpp translate.h + +snooper: snooper.o gui.o command.o usb.o guidummy.o + +cli: cli.o gui.o command.o usb.o guidummy.o + +flasher: flasher.o usb.o + +proxguiqt.moc.cpp: proxguiqt.h + $(MOC) -o$@ $^ + +clean: + rm -f cli flasher proxmark3 snooper *.o *.moc.cpp + +.PHONY: all clean diff --git a/client/Makefile.win b/client/Makefile.win new file mode 100644 index 00000000..1c8287f8 --- /dev/null +++ b/client/Makefile.win @@ -0,0 +1,33 @@ +CC=cl +BASE_DIR ?= "..\..\devkitWIN" +BASE_DEFS = /D_WIN32_WINNT=0x501 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x600 /DWIN32_LEAN_AND_MEAN /DWIN32 /D_MT /D_CRT_SECURE_NO_WARNINGS +BASE_CFLAGS = /W3 /nologo /Zi /MT /Fdobj/vc90.pdb +LIB = $(BASE_DIR)\lib + +DEFINES = $(BASE_DEFS) +INCLUDES = /I$(BASE_DIR)\include +CFLAGS = $(BASE_CFLAGS) $(INCLUDES) + +OBJDIR = obj + +OBJS = $(OBJDIR)\prox.obj \ + $(OBJDIR)\gui.obj \ + $(OBJDIR)\command.obj + +LIBS = $(LIB)\user32.lib $(LIB)\gdi32.lib $(LIB)\setupapi.lib $(LIB)\libcmt.lib $(LIB)\oldnames.lib $(LIB)\kernel32.lib + +all: proxmark3 + +proxmark3: + $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/prox.obj prox.cpp + $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/gui.obj gui.cpp + $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/command.obj command.cpp + $(CC) $(CFLAGS) $(DEFINES) -Fe$(OBJDIR)/prox.exe $(OBJS) $(LIBS) + copy obj\prox.exe . + +clean: + del /q obj\*.obj + del /q obj\*.ilk + del /q obj\*.exe + del /q obj\*.pdb + del prox.exe \ No newline at end of file diff --git a/client/cli.c b/client/cli.c new file mode 100644 index 00000000..3e8aab60 --- /dev/null +++ b/client/cli.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "translate.h" +#include "prox.h" +#include "proxmark3.h" + +#define HANDLE_ERROR if (error_occured) { \ + 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++) { + ReceiveCommandP(&cmdbuf); + } + HANDLE_ERROR + + CommandReceived(argv[2]); + HANDLE_ERROR + } + } + + CloseProxmark(); + return 0; +} diff --git a/client/command.c b/client/command.c new file mode 100644 index 00000000..ceda9a27 --- /dev/null +++ b/client/command.c @@ -0,0 +1,2 @@ +#include "translate.h" +#include "command.cpp" diff --git a/client/command.cpp b/client/command.cpp new file mode 100644 index 00000000..0214a0ab --- /dev/null +++ b/client/command.cpp @@ -0,0 +1,3093 @@ +//----------------------------------------------------------------------------- +// 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 (##) +//----------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include "prox.h" +#include "../common/iso14443_crc.c" +#include "../common/crc16.c" + +#define arraylen(x) (sizeof(x)/sizeof((x)[0])) +#define BIT(x) GraphBuffer[x * clock] +#define BITS (GraphTraceLen / clock) + +int go = 0; +static int CmdHisamplest(char *str, int nrlow); + +static void GetFromBigBuf(BYTE *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; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return; + } + + memcpy(dest+(i*4), c.d.asBytes, 48); + } +} + +static void CmdReset(char *str) +{ + UsbCommand c; + c.cmd = CMD_HARDWARE_RESET; + SendCommand(&c, FALSE); +} + +static void CmdBuffClear(char *str) +{ + UsbCommand c; + c.cmd = CMD_BUFF_CLEAR; + SendCommand(&c, FALSE); + CmdClearGraph(TRUE); +} + +static void CmdQuit(char *str) +{ + exit(0); +} + +static void CmdHIDdemodFSK(char *str) +{ + UsbCommand c; + c.cmd = CMD_HID_DEMOD_FSK; + SendCommand(&c, FALSE); +} + +static void CmdTune(char *str) +{ + UsbCommand c; + c.cmd = CMD_MEASURE_ANTENNA_TUNING; + SendCommand(&c, FALSE); +} + +static void CmdHi15read(char *str) +{ + UsbCommand c; + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693; + SendCommand(&c, FALSE); +} + +static void CmdHi14read(char *str) +{ + UsbCommand c; + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + + +/* 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; + c.cmd = CMD_READ_SRI512_TAG; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +/* 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; + c.cmd = CMD_READ_SRIX4K_TAG; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + + + +// ## New command +static void CmdHi14areader(char *str) +{ + UsbCommand c; + c.cmd = CMD_READER_ISO_14443a; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +// ## New command +static void CmdHi15reader(char *str) +{ + UsbCommand c; + c.cmd = CMD_READER_ISO_15693; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +// ## New command +static void CmdHi15tag(char *str) +{ + UsbCommand c; + c.cmd = CMD_SIMTAG_ISO_15693; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +static void CmdHi14read_sim(char *str) +{ + UsbCommand c; + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +static void CmdHi14readt(char *str) +{ + UsbCommand c; + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); + + //CmdHisamplest(str); + while(CmdHisamplest(str,atoi(str))==0) { + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); + } + RepaintGraphWindow(); +} + +static void CmdHisimlisten(char *str) +{ + UsbCommand c; + c.cmd = CMD_SIMULATE_TAG_HF_LISTEN; + SendCommand(&c, FALSE); +} + +static void CmdHi14sim(char *str) +{ + UsbCommand c; + c.cmd = CMD_SIMULATE_TAG_ISO_14443; + SendCommand(&c, FALSE); +} + +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; + UsbCommand c; + + while (sscanf(&str[i++], "%1x", &n ) == 1) { + hi=(hi<<4)|(lo>>28); + lo=(lo<<4)|(n&0xf); + } + + c.cmd = CMD_SIMULATE_TAG_ISO_14443a; + // c.ext should be set to *str or convert *str to the correct format for a uid + c.ext1 = hi; + c.ext2 = lo; + PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo); + SendCommand(&c, FALSE); +} + +static void CmdHi14snoop(char *str) +{ + UsbCommand c; + c.cmd = CMD_SNOOP_ISO_14443; + SendCommand(&c, FALSE); +} + +static void CmdHi14asnoop(char *str) +{ + UsbCommand c; + c.cmd = CMD_SNOOP_ISO_14443a; + SendCommand(&c, FALSE); +} + +static void CmdLegicRfSim(char *str) +{ + UsbCommand c; + c.cmd = CMD_SIMULATE_TAG_LEGIC_RF; + SendCommand(&c, FALSE); +} + +static void CmdLegicRfRead(char *str) +{ + UsbCommand c; + c.cmd = CMD_READER_LEGIC_RF; + SendCommand(&c, FALSE); +} + +static void CmdFPGAOff(char *str) // ## FPGA Control +{ + UsbCommand c; + c.cmd = CMD_FPGA_MAJOR_MODE_OFF; + SendCommand(&c, FALSE); +} + +/* 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]; + char *s = "0"; + + /* 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(s); + + /* booyah! */ + RepaintGraphWindow(); + + CmdLosim(s); +} + +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; + + /* convert to bitstream if necessary */ + ChkBitstream(str); + + for (i = 0; i < GraphTraceLen; i += 48) { + UsbCommand c; + int j; + for(j = 0; j < 48; j++) { + c.d.asBytes[j] = GraphBuffer[i+j]; + } + c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + } + + UsbCommand c; + c.cmd = CMD_SIMULATE_TAG_125K; + c.ext1 = GraphTraceLen; + SendCommand(&c, FALSE); +} + +static void CmdLosimBidir(char *str) +{ + UsbCommand c; + c.cmd = CMD_LF_SIMULATE_BIDIR; + c.ext1 = 47; /* Set ADC to twice the carrier for a slight supersampling */ + c.ext2 = 384; + SendCommand(&c, FALSE); +} + +static void CmdLoread(char *str) +{ + UsbCommand c; + // 'h' means higher-low-frequency, 134 kHz + if(*str == 'h') { + c.ext1 = 1; + } else if (*str == '\0') { + c.ext1 = 0; + } else { + PrintToScrollback("use 'loread' or 'loread h'"); + return; + } + c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K; + SendCommand(&c, FALSE); +} + +static void CmdDetectReader(char *str) +{ + UsbCommand c; + // 'l' means LF - 125/134 kHz + if(*str == 'l') { + c.ext1 = 1; + } else if (*str == 'h') { + c.ext1 = 2; + } else if (*str != '\0') { + PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); + return; + } + c.cmd = CMD_LISTEN_READER_FIELD; + SendCommand(&c, FALSE); +} + +/* send a command before reading */ +static void CmdLoCommandRead(char *str) +{ + static char dummy[3]; + + dummy[0]= ' '; + + UsbCommand c; + c.cmd = CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K; + sscanf(str, "%i %i %i %s %s", &c.ext1, &c.ext2, &c.ext3, (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, FALSE); +} + +static void CmdLosamples(char *str) +{ + int cnt = 0; + int i; + int n; + + n=atoi(str); + if (n==0) n=128; + if (n>16000) n=16000; + + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + if (!go) + PrintToScrollback("bad resp"); + return; + } + int j; + for(j = 0; j < 48; j++) { + GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128; + } + } + GraphTraceLen = n*4; + RepaintGraphWindow(); +} + +static void CmdBitsamples(char *str) +{ + int cnt = 0; + int i; + int n; + + n = 3072; + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return; + } + int j, k; + for(j = 0; j < 48; j++) { + for(k = 0; k < 8; k++) { + if(c.d.asBytes[j] & (1 << (7 - k))) { + GraphBuffer[cnt++] = 1; + } else { + GraphBuffer[cnt++] = 0; + } + } + } + } + GraphTraceLen = cnt; + RepaintGraphWindow(); +} + +static void CmdHisamples(char *str) +{ + int cnt = 0; + int i; + int n; + n = 1000; + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return; + } + int j; + for(j = 0; j < 48; j++) { + GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]); + } + } + GraphTraceLen = n*4; + + RepaintGraphWindow(); +} + +static int CmdHisamplest(char *str, int nrlow) +{ + int cnt = 0; + int t1, t2; + int i; + int n; + int hasbeennull; + int show; + + + n = 1000; + hasbeennull = 0; + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return 0; + } + int j; + for(j = 0; j < 48; j++) { + t2 = (int)((BYTE)c.d.asBytes[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; + int n; + int requested = atoi(str); + int delivered = 0; + + if(atoi(str) == 0) { + n = 12; + requested = 12; + } else { + n = atoi(str)/4; + } + + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return; + } + int j; + for(j = 0; j < 48; j += 8) { + PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", + c.d.asBytes[j+0], + c.d.asBytes[j+1], + c.d.asBytes[j+2], + c.d.asBytes[j+3], + c.d.asBytes[j+4], + c.d.asBytes[j+5], + c.d.asBytes[j+6], + c.d.asBytes[j+7], + c.d.asBytes[j+8] + ); + delivered += 8; + if(delivered >= requested) + break; + } + if(delivered >= requested) + break; + } +} + +static void CmdHisampless(char *str) +{ + int cnt = 0; + int i; + int n; + + if(atoi(str) == 0) { + n = 1000; + } else { + n = atoi(str)/4; + } + + for(i = 0; i < n; i += 12) { + UsbCommand c; + c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; + c.ext1 = i; + SendCommand(&c, FALSE); + ReceiveCommand(&c); + if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { + PrintToScrollback("bad resp"); + return; + } + int j; + for(j = 0; j < 48; j++) { + GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]); + } + } + GraphTraceLen = cnt; + + RepaintGraphWindow(); +} + +static WORD Iso15693Crc(BYTE *v, int n) +{ + DWORD reg; + int i, j; + + reg = 0xffff; + for(i = 0; i < n; i++) { + reg = reg ^ ((DWORD)v[i]); + for (j = 0; j < 8; j++) { + if (reg & 0x0001) { + reg = (reg >> 1) ^ 0x8408; + } else { + reg = (reg >> 1); + } + } + } + + return (WORD)~reg; +} + +static void CmdHi14bdemod(char *str) +{ + int i, j, iold; + int isum, qsum; + int outOfWeakAt; + BOOL negateI, negateQ; + + BYTE 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; + + WORD 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; + } + } + + BYTE 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) +{ + BYTE 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 = *((DWORD *)(got+i)); + if(timestamp & 0x80000000) { + timestamp &= 0x7fffffff; + isResponse = 1; + } else { + isResponse = 0; + } + int metric = *((DWORD *)(got+i+4)); + + int len = got[i+8]; + + if(len > 100) { + break; + } + if(i + len >= 900) { + break; + } + + BYTE *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) { + BYTE 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) +{ + BYTE 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 = *((DWORD *)(got+i)); + if(timestamp & 0x80000000) { + timestamp &= 0x7fffffff; + isResponse = 1; + } else { + isResponse = 0; + } + + int metric = 0; + int parityBits = *((DWORD *)(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; + } + + BYTE *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) { + BYTE 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; + BYTE outBuf[20]; + memset(outBuf, 0, sizeof(outBuf)); + BYTE 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; + DWORD 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); + + BYTE 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; + c.cmd = CMD_READ_TI_TYPE; + SendCommand(&c, FALSE); +} + +// write new data to a r/w TI tag +static void CmdTIWrite(char *str) +{ + UsbCommand c; + int res=0; + + c.cmd = CMD_WRITE_TI_TYPE; + res = sscanf(str, "0x%x 0x%x 0x%x ", &c.ext1, &c.ext2, &c.ext3); + if (res == 2) c.ext3=0; + if (res<2) + PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third"); + else + SendCommand(&c, FALSE); +} + +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; + WORD 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); + + BYTE bits[1+64+16+8+16]; + bits[sizeof(bits)-1] = '\0'; + + DWORD 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 + BYTE 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 + BYTE 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; + + BYTE 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; + UsbCommand c; + + 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); + + c.cmd = CMD_HID_SIM_TAG; + c.ext1 = hi; + c.ext2 = lo; + SendCommand(&c, FALSE); +} + +static void CmdReadmem(char *str) +{ + UsbCommand c; + c.cmd = CMD_READ_MEM; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +static void CmdVersion(char *str) +{ + UsbCommand c; + c.cmd = CMD_VERSION; + SendCommand(&c, FALSE); +} + +static void CmdLcdReset(char *str) +{ + UsbCommand c; + c.cmd = CMD_LCD_RESET; + c.ext1 = atoi(str); + SendCommand(&c, FALSE); +} + +static void CmdLcd(char *str) +{ + int i, j; + UsbCommand c; + c.cmd = CMD_LCD; + sscanf(str, "%x %d", &i, &j); + while (j--) { + c.ext1 = i&0x1ff; + SendCommand(&c, FALSE); + } +} + +/* + * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below + * 600kHz. + */ +static void CmdSetDivisor(char *str) +{ + UsbCommand c; + c.cmd = CMD_SET_LF_DIVISOR; + c.ext1 = atoi(str); + if (( c.ext1<0) || (c.ext1>255)) { + PrintToScrollback("divisor must be between 19 and 255"); + } else { + SendCommand(&c, FALSE); + PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1)); + } +} + +static void CmdSetMux(char *str) +{ + UsbCommand c; + c.cmd = CMD_SET_ADC_MUX; + if(strcmp(str, "lopkd") == 0) { + c.ext1 = 0; + } else if(strcmp(str, "loraw") == 0) { + c.ext1 = 1; + } else if(strcmp(str, "hipkd") == 0) { + c.ext1 = 2; + } else if(strcmp(str, "hiraw") == 0) { + c.ext1 = 3; + } + SendCommand(&c, FALSE); +} + +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[] = { + {"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"}, + {"detectreader", CmdDetectReader, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"em410xsim", CmdEM410xsim, 1, " -- Simulate EM410x tag"}, + {"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"}, + {"exit", CmdQuit, 1, "Exit program"}, + {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"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"}, + {"hi14alist", CmdHi14alist, 0, "List ISO 14443a history"}, + {"hi14areader", CmdHi14areader, 0, "Act like an ISO14443 Type A reader"}, + {"hi14asim", CmdHi14asim, 0, " -- Fake ISO 14443a tag"}, + {"hi14asnoop", CmdHi14asnoop, 0, "Eavesdrop ISO 14443 Type A"}, + {"hi14bdemod", CmdHi14bdemod, 1, "Demodulate ISO14443 Type B from tag"}, + {"hi14list", CmdHi14list, 0, "List ISO 14443 history"}, + {"hi14read", CmdHi14read, 0, "Read HF tag (ISO 14443)"}, + {"hi14sim", CmdHi14sim, 0, "Fake ISO 14443 tag"}, + {"hi14snoop", CmdHi14snoop, 0, "Eavesdrop ISO 14443"}, + {"hi15demod", CmdHi15demod, 1, "Demodulate ISO15693 from tag"}, + {"hi15read", CmdHi15read, 0, "Read HF tag (ISO 15693)"}, + {"hi15reader", CmdHi15reader, 0, "Act like an ISO15693 reader"}, + {"hi15sim", CmdHi15tag, 0, "Fake an ISO15693 tag"}, + {"hiddemod", CmdHiddemod, 1, "Demodulate HID Prox Card II (not optimal)"}, + {"hide", CmdHide, 1, "Hide graph window"}, + {"hidfskdemod", CmdHIDdemodFSK, 0, "Realtime HID FSK demodulator"}, + {"hidsimtag", CmdHIDsimTAG, 0, " -- HID tag simulator"}, + {"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"}, + {"hisimlisten", CmdHisimlisten, 0, "Get HF samples as fake tag"}, + {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, + {"indalademod", CmdIndalademod, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, + {"lcd", CmdLcd, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLcdReset, 0, "Hardware reset LCD"}, + {"legicrfsim", CmdLegicRfSim, 0, "Start the LEGIC RF tag simulator"}, + {"legicrfread", CmdLegicRfRead, 0, "Start the LEGIC RF reader"}, + {"load", CmdLoad, 1, " -- Load trace (to graph window"}, + {"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)"}, + {"losamples", CmdLosamples, 0, "[128 - 16000] -- Get raw samples for LF tag"}, + {"losim", CmdLosim, 0, "Simulate LF tag"}, + {"losimbidir", CmdLosimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, + {"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"}, + {"quit", CmdQuit, 1, "Quit program"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"save", CmdSave, 1, " -- Save trace (from graph window)"}, + {"scale", CmdScale, 1, " -- Set cursor display scale"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"sri512read", CmdSri512read, 0, " -- Read contents of a SRI512 tag"}, + {"srix4kread", CmdSrix4kread, 0, " -- Read contents of a SRIX4K tag"}, + {"tidemod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF 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"}, + {"threshold", CmdThreshold, 1, "Maximize/minimize every value in the graph window depending on threshold"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"vchdemod", CmdVchdemod, 0, "['clone'] -- Demodulate samples for VeriChip"}, + {"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"}, + {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, +}; + +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[256]; + + 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) +{ + switch(c->cmd) { + case CMD_DEBUG_PRINT_STRING: { + char s[100]; + if(c->ext1 > 70 || c->ext1 < 0) { + c->ext1 = 0; + } + memcpy(s, c->d.asBytes, c->ext1); + s[c->ext1] = '\0'; + PrintToScrollback("#db# %s", s); + break; + } + + case CMD_DEBUG_PRINT_INTEGERS: + PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3); + break; + + case CMD_MEASURED_ANTENNA_TUNING: { + int peakv, peakf; + int vLf125, vLf134, vHf; + vLf125 = c->ext1 & 0xffff; + vLf134 = c->ext1 >> 16; + vHf = c->ext2 & 0xffff;; + peakf = c->ext3 & 0xffff; + peakv = c->ext3 >> 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."); + break; + } + default: + PrintToScrollback("unrecognized command %08x\n", c->cmd); + break; + } +} diff --git a/client/flasher.c b/client/flasher.c new file mode 100644 index 00000000..e3043fa3 --- /dev/null +++ b/client/flasher.c @@ -0,0 +1,355 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "translate.h" +#include "prox.h" +#include "proxmark3.h" + +static DWORD ExpectedAddr; +static BYTE QueuedToSend[256]; +static BOOL AllWritten; +#define PHYSICAL_FLASH_START 0x100000 + +struct partition { + int start; + int end; + int precious; + const char *name; +}; +struct partition partitions[] = { + {0x100000, 0x102000, 1, "bootrom"}, + {0x102000, 0x110000, 0, "fpga"}, + {0x110000, 0x140000, 0, "os"}, +}; + +/* If translate is set, subtract PHYSICAL_FLASH_START to translate for old + * bootroms. + */ +static void FlushPrevious(int translate) +{ + UsbCommand c; + memset(&c, 0, sizeof(c)); + + printf("expected = %08x flush, ", ExpectedAddr); + + int i; + for(i = 0; i < 240; i += 48) { + c.cmd = CMD_SETUP_WRITE; + memcpy(c.d.asBytes, QueuedToSend+i, 48); + c.ext1 = (i/4); + SendCommand(&c, TRUE); + } + + c.cmd = CMD_FINISH_WRITE; + c.ext1 = (ExpectedAddr-1) & (~255); + if(translate) { + c.ext1 -= PHYSICAL_FLASH_START; + } + printf("c.ext1 = %08x\r", c.ext1); + memcpy(c.d.asBytes, QueuedToSend+240, 16); + SendCommand(&c, TRUE); + + AllWritten = TRUE; +} + +/* Where must be between start_addr (inclusive) and end_addr (exclusive). + */ +static void GotByte(DWORD where, BYTE which, int start_addr, int end_addr, int translate) +{ + AllWritten = FALSE; + + if(where < start_addr || where >= end_addr) { + printf("bad: got byte at %08x, outside of range %08x-%08x\n", where, start_addr, end_addr); + exit(-1); + } + + if(where != ExpectedAddr) { + printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr); + exit(-1); + } + QueuedToSend[where & 255] = which; + ExpectedAddr++; + + if((where & 255) == 255) { + // we have completed a full page + FlushPrevious(translate); + } +} + +static int HexVal(int c) +{ + c = tolower(c); + if(c >= '0' && c <= '9') { + return c - '0'; + } else if(c >= 'a' && c <= 'f') { + return (c - 'a') + 10; + } else { + printf("bad hex digit '%c'\n", c); + exit(-1); + } +} + +static BYTE HexByte(char *s) +{ + return (HexVal(s[0]) << 4) | HexVal(s[1]); +} + +static void LoadFlashFromSRecords(const char *file, int start_addr, int end_addr, int translate) +{ + ExpectedAddr = start_addr; + + FILE *f = fopen(file, "r"); + if(!f) { + printf("couldn't open file\n"); + exit(-1); + } + + char line[512]; + while(fgets(line, sizeof(line), f)) { + if(memcmp(line, "S3", 2)==0) { + char *s = line + 2; + int len = HexByte(s) - 5; + s += 2; + + char addrStr[9]; + memcpy(addrStr, s, 8); + addrStr[8] = '\0'; + DWORD addr; + sscanf(addrStr, "%x", &addr); + s += 8; + + /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */ + if(addr < PHYSICAL_FLASH_START) + addr += PHYSICAL_FLASH_START; + + int i; + for(i = 0; i < len; i++) { + while((addr+i) > ExpectedAddr) { + GotByte(ExpectedAddr, 0xff, start_addr, end_addr, translate); + } + GotByte(addr+i, HexByte(s), start_addr, end_addr, translate); + s += 2; + } + } + } + + if(!AllWritten) FlushPrevious(translate); + + fclose(f); + printf("\ndone.\n"); +} + +static int PrepareFlash(struct partition *p, const char *filename, unsigned int state) +{ + int translate = 0; + if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { + UsbCommand c; + c.cmd = CMD_START_FLASH; + c.ext1 = p->start; + c.ext2 = p->end; + + /* Only send magic when flashing bootrom */ + if(p->precious) { + c.ext3 = START_FLASH_MAGIC; + } else { + c.ext3 = 0; + } + SendCommand(&c, TRUE); + translate = 0; + } 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"); + translate = 1; + } + + LoadFlashFromSRecords(filename, p->start, p->end, translate); + return 1; +} + +static unsigned int GetProxmarkState(void) +{ + unsigned int state = 0; + + UsbCommand c; + c.cmd = CMD_DEVICE_INFO; + SendCommand(&c, FALSE); + + 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.ext1; + break; + default: + fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); + exit(-1); + break; + } + +#if 0 + if(state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) printf("New bootrom present\n"); + if(state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) printf("New osimage present\n"); + if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) printf("Currently in bootrom\n"); + if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) printf("Currently in OS\n"); +#endif + + return state; +} + +static 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, FALSE); + 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, FALSE); + fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); + fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); + } + + CloseProxmark(); + sleep(1); + + while(!(devh=OpenProxmark(0))) { sleep(1); } + fprintf(stderr,"Found.\n"); + + return GetProxmarkState(); + } + + return 0; +} + +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:"); + for(i=0; i<(sizeof(partitions)/sizeof(partitions[0])); 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.s19 path/to/fpgaimage.s19\n", argv[0]); +} + +/* On first call, have *offset = -1, *length = 0; */ +static 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; +} + +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(!(devh=OpenProxmark(0))) { sleep(1); } + fprintf(stderr,"Found.\n"); + + unsigned int state = EnterFlashState(); + + if( !(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) ) { + fprintf(stderr, "Proxmark would not enter flash state, abort\n"); + exit(-1); + } + + 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++; + } + + UsbCommand c; + bzero(&c, sizeof(c)); + c.cmd = CMD_HARDWARE_RESET; + SendCommand(&c, FALSE); + + CloseProxmark(); + + fprintf(stderr,"Have a nice day!\n"); + + return 0; +} diff --git a/client/gui.c b/client/gui.c new file mode 100644 index 00000000..c540f9e8 --- /dev/null +++ b/client/gui.c @@ -0,0 +1,58 @@ +#include +#include +#include + +#include "proxgui.h" +#include "translate.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/gui.cpp b/client/gui.cpp new file mode 100644 index 00000000..3753a86e --- /dev/null +++ b/client/gui.cpp @@ -0,0 +1,533 @@ +//----------------------------------------------------------------------------- +// Routines for the user interface when doing interactive things with prox +// cards; this is basically a command line thing, in one window, and then +// another window to do the graphs. +// Jonathan Westhues, Sept 2005 +//----------------------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +#include "prox.h" + +#define oops() do { \ + char line[100]; \ + sprintf(line, "Internal error at line %d file '%s'", __LINE__, \ + __FILE__); \ + MessageBox(NULL, line, "Error", MB_ICONERROR); \ + exit(-1); \ +} while(0) + +void dbp(char *str, ...) +{ + va_list f; + char buf[1024]; + va_start(f, str); + vsprintf(buf, str, f); + OutputDebugString(buf); + OutputDebugString("\n"); +} + +int GraphBuffer[MAX_GRAPH_TRACE_LEN]; +int GraphTraceLen; +int PlotGridX, PlotGridY; + +HPEN GreyPenLite, GreyPen, GreenPen, WhitePen, YellowPen; +HBRUSH GreenBrush, YellowBrush; + +static int GraphStart = 0; +static double GraphPixelsPerPoint = 1; + +static int CursorAPos; +static int CursorBPos; +double CursorScaleFactor = 1.0; +static HPEN CursorAPen; +static HPEN CursorBPen; + +static HWND CommandWindow; +static HWND GraphWindow; +static HWND ScrollbackEdit; +static HWND CommandEdit; + +#define COMMAND_HISTORY_MAX 16 +static char CommandHistory[COMMAND_HISTORY_MAX][256]; +static int CommandHistoryPos = -1; +static int CommandHistoryNext; + +static HFONT MyFixedFont; +#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE) + +void ExecCmd(char *cmd) +{ +} + +int CommandFinished; +int offset = 64; + +static void ResizeCommandWindow(void) +{ + int w, h; + RECT r; + GetClientRect(CommandWindow, &r); + w = r.right - r.left; + h = r.bottom - r.top; + MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE); + MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE); +} + +void RepaintGraphWindow(void) +{ + InvalidateRect(GraphWindow, NULL, TRUE); +} + +static LRESULT CALLBACK + CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_DESTROY: + case WM_QUIT: + exit(0); + return 0; + + case WM_SIZE: + ResizeCommandWindow(); + return 0; + + case WM_SETFOCUS: + SetFocus(CommandEdit); + break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + return 1; +} + +static void PaintGraph(HDC hdc) +{ + RECT r; + HBRUSH brush; + HPEN pen; + char str[250]; + int yMin = INT_MAX; + int yMax = INT_MIN; + int yMean = 0; + int startMax = 0; + int absYMax = 1; + int n = 0, i = 0; + + brush = GreenBrush; + pen = GreenPen; + + GetClientRect(GraphWindow, &r); + int zeroHeight = (r.top + r.bottom) >> 1; + + // plot X and Y grid lines + if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) { + for(i = offset; i < r.right; i += (int)(PlotGridX * GraphPixelsPerPoint)) { + SelectObject(hdc, GreyPenLite); + MoveToEx(hdc, r.left + i, r.top, NULL); + LineTo(hdc, r.left + i, r.bottom); + } + } + + if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){ + for(i = 0; i < ((r.top + r.bottom)>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) { + SelectObject(hdc, GreyPenLite); + MoveToEx(hdc, r.left, zeroHeight + i, NULL); + LineTo(hdc, r.right, zeroHeight + i); + MoveToEx(hdc, r.left, zeroHeight - i, NULL); + LineTo(hdc, r.right, zeroHeight - i); + } + } + + // print vertical separator white line on the left of the window + SelectObject(hdc, WhitePen); + MoveToEx(hdc, r.left + offset, r.top, NULL); + LineTo(hdc, r.left + offset, r.bottom); + + // print horizontal grey zero axis line + SelectObject(hdc, GreyPen); + MoveToEx(hdc, r.left, zeroHeight, NULL); + LineTo(hdc, r.right, zeroHeight); + + startMax = (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint)); + // check boundaries + if(startMax < 0) startMax = 0; + if(GraphStart > startMax) GraphStart = startMax; + if(GraphStart < 0) GraphStart = 0; + + + SelectObject(hdc, pen); + + // go over the portion of the graph to be displayed and find the largest + // absolute value which will be used to auto scale the graph when displayed + for(i = GraphStart; ; i++) { + if(i >= GraphTraceLen) { + break; + } + if(fabs((double)GraphBuffer[i]) > absYMax) { + absYMax = (int)fabs((double)GraphBuffer[i]); + } + int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint); + if(x > r.right) { + break; + } + } + + absYMax = (int)(absYMax*1.2 + 1); + SelectObject(hdc, MyFixedFont); + SetTextColor(hdc, RGB(255, 255, 255)); + SetBkColor(hdc, RGB(0, 0, 0)); + + // number of points that will be plotted + double span = (int)((r.right - r.left) / GraphPixelsPerPoint); + + // one label every offset pixels, let us say + int labels = (r.right - r.left - offset) / offset; + if(labels <= 0) labels = 1; + // round to nearest power of 2 + int pointsPerLabel = (int)(log(span / labels)/log(2.0)); + if(pointsPerLabel <= 0) pointsPerLabel = 1; + pointsPerLabel = (int)pow(2.0,pointsPerLabel); + + // go over the graph and plot samples and labels + for(i = GraphStart; ; i++) { + if(i >= GraphTraceLen) { + break; + } + int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint); + if(x > r.right + GraphPixelsPerPoint) { + break; + } + + int y = GraphBuffer[i]; + if(y < yMin) yMin = y; + if(y > yMax) yMax = y; + yMean += y; + n++; + + y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight; + if(i == GraphStart) { + MoveToEx(hdc, x, y, NULL); + } else { + LineTo(hdc, x, y); + } + + if(GraphPixelsPerPoint > 10) { + RECT f; + f.left = x - 3; + f.top = y - 3; + f.right = x + 3; + f.bottom = y + 3; + FillRect(hdc, &f, brush); + } + + // plot labels + if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) { + SelectObject(hdc, WhitePen); + MoveToEx(hdc, x, zeroHeight - 8, NULL); + LineTo(hdc, x, zeroHeight + 8); + + sprintf(str, "+%d", i); + SIZE size; + GetTextExtentPoint32(hdc, str, strlen(str), &size); + TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str)); + + SelectObject(hdc, pen); + MoveToEx(hdc, x, y, NULL); + } + + // plot measurement cursors + if(i == CursorAPos || i == CursorBPos) { + if(i == CursorAPos) { + SelectObject(hdc, CursorAPen); + } else { + SelectObject(hdc, CursorBPen); + } + MoveToEx(hdc, x, r.top, NULL); + LineTo(hdc, x, r.bottom); + + SelectObject(hdc, pen); + MoveToEx(hdc, x, y, NULL); + } + } + + if(n != 0) { + yMean /= n; + } + + // print misc information at bottom of graph window + sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]", + GraphStart, yMax, yMin, yMean, n, GraphTraceLen, + CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint, + CursorAPos, GraphBuffer[CursorAPos], CursorBPos, GraphBuffer[CursorBPos]); + TextOut(hdc, 50, r.bottom - 20, str, strlen(str)); +} + +static LRESULT CALLBACK + GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_DESTROY: + case WM_QUIT: + GraphWindow = NULL; + return DefWindowProc(hwnd, msg, wParam, lParam); + + case WM_SIZE: + RepaintGraphWindow(); + return 0; + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + if(GraphStart < 0) { + GraphStart = 0; + } + // This draws the trace. + PaintGraph(hdc); + EndPaint(hwnd, &ps); + break; + } + case WM_KEYDOWN: + switch(wParam) { + case VK_DOWN: + if(GraphPixelsPerPoint <= 8) { + GraphPixelsPerPoint *= 2; + } + break; + + case VK_UP: + if(GraphPixelsPerPoint >= 0.01) { + GraphPixelsPerPoint /= 2; + } + break; + + case VK_RIGHT: + if(GraphPixelsPerPoint < 16) { + GraphStart += (int)(16 / GraphPixelsPerPoint); + } else { + GraphStart++; + } + break; + + case VK_LEFT: + if(GraphPixelsPerPoint < 16) { + GraphStart -= (int)(16 / GraphPixelsPerPoint); + } else { + GraphStart--; + } + break; + + default: + goto nopaint; + } + RepaintGraphWindow(); +nopaint: + break; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: { + int x = LOWORD(lParam); + x -= offset; + x = (int)(x / GraphPixelsPerPoint); + x += GraphStart; + + if(msg == WM_LBUTTONDOWN) { + CursorAPos = x; + } else { + CursorBPos = x; + } + RepaintGraphWindow(); + break; + } + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + return 1; +} + +void PrintToScrollback(char *fmt, ...) +{ + va_list f; + char str[1024]; + strcpy(str, "\r\n"); + va_start(f, fmt); + vsprintf(str+2, fmt, f); + + static char TextBuf[1024*32]; + SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf), + (LPARAM)TextBuf); + + if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) { + strcat(TextBuf, str); + } else { + lstrcpyn(TextBuf, str, sizeof(TextBuf)); + } + + SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf); + SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX); +} + +void ShowGraphWindow(void) +{ + if(GraphWindow) return; + + GraphWindow = CreateWindowEx(0, "Graph", "graphed", + WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | + WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL, + NULL); + if(!GraphWindow) oops(); +} + +void HideGraphWindow(void) +{ + if(GraphWindow) { + DestroyWindow(GraphWindow); + GraphWindow = NULL; + } +} + +static void SetCommandEditTo(char *str) +{ + SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str); + SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str)); +} + +void ShowGui() +{ + WNDCLASSEX wc; + memset(&wc, 0, sizeof(wc)); + wc.cbSize = sizeof(wc); + + wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)CommandWindowProc; + wc.hInstance = NULL; + wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW); + wc.lpszClassName = "Command"; + wc.lpszMenuName = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + + if(!RegisterClassEx(&wc)) oops(); + + wc.lpszClassName = "Graph"; + wc.lpfnWndProc = (WNDPROC)GraphWindowProc; + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + + if(!RegisterClassEx(&wc)) oops(); + + CommandWindow = CreateWindowEx(0, "Command", "prox", + WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | + WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL, + NULL); + if(!CommandWindow) oops(); + + ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "", + WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE | + ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL, + NULL, NULL); + + CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "", + WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE | + ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL); + + MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + FF_DONTCARE, "Lucida Console"); + if(!MyFixedFont) + MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT); + + FixedFont(ScrollbackEdit); + FixedFont(CommandEdit); + + ResizeCommandWindow(); + SetFocus(CommandEdit); + + PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__); + PrintToScrollback(">> Connected to device"); + + GreyPenLite = CreatePen(PS_SOLID, 1, RGB(50, 50, 50)); + GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100)); + GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100)); + YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0)); + GreenBrush = CreateSolidBrush(RGB(100, 255, 100)); + YellowBrush = CreateSolidBrush(RGB(255, 255, 0)); + WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); + + CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0)); + CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255)); + + MSG msg; + for(;;) { + if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) { + char got[1024]; + SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got), + (LPARAM)got); + + if(strcmp(got, "cls")==0) { + SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)""); + } else { + CommandReceived(got); + } + SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)""); + + // Insert it into the command history, unless it is + // identical to the previous command in the history. + int prev = CommandHistoryNext - 1; + if(prev < 0) prev += COMMAND_HISTORY_MAX; + if(strcmp(CommandHistory[prev], got) != 0) { + strcpy(CommandHistory[CommandHistoryNext], got); + CommandHistoryNext++; + if(CommandHistoryNext == COMMAND_HISTORY_MAX) { + CommandHistoryNext = 0; + } + } + CommandHistoryPos = -1; + } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP && + msg.hwnd == CommandEdit) + { + if(CommandHistoryPos == -1) { + CommandHistoryPos = CommandHistoryNext; + } + CommandHistoryPos--; + if(CommandHistoryPos < 0) { + CommandHistoryPos = COMMAND_HISTORY_MAX-1; + } + SetCommandEditTo(CommandHistory[CommandHistoryPos]); + } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN && + msg.hwnd == CommandEdit) + { + CommandHistoryPos++; + if(CommandHistoryPos >= COMMAND_HISTORY_MAX) { + CommandHistoryPos = 0; + } + SetCommandEditTo(CommandHistory[CommandHistoryPos]); + } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE && + msg.hwnd == CommandEdit) + { + SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)""); + } else { + if(msg.message == WM_KEYDOWN) { + CommandHistoryPos = -1; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (!offline) + { + UsbCommand c; + if(ReceiveCommandPoll(&c)) + UsbCommandReceived(&c); + } + + Sleep(10); + } +} diff --git a/client/guidummy.c b/client/guidummy.c new file mode 100644 index 00000000..39bcc756 --- /dev/null +++ b/client/guidummy.c @@ -0,0 +1,17 @@ +#include + +void ShowGraphWindow(void) +{ + static int warned = 0; + + if (!warned) { + printf("No GUI in this build!\n"); + warned = 1; + } +} + +void HideGraphWindow(void) {} +void RepaintGraphWindow(void) {} +void MainGraphics() {} +void InitGraphics(int argc, char **argv) {} +void ExitGraphics(void) {} diff --git a/client/include/hidpi.h b/client/include/hidpi.h new file mode 100644 index 00000000..e9816cf4 --- /dev/null +++ b/client/include/hidpi.h @@ -0,0 +1,1787 @@ +/*++ + +Copyright (c) 1996-1998 Microsoft Corporation + +Module Name: + + HIDPI.H + +Abstract: + + Public Interface to the HID parsing library. + +Environment: + + Kernel & user mode + +--*/ + +#ifndef __HIDPI_H__ +#define __HIDPI_H__ + +#include + +// Please include "hidsdi.h" to use the user space (dll / parser) +// Please include "hidpddi.h" to use the kernel space parser + +// +// Special Link collection values for using the query functions +// +// Root collection references the collection at the base of the link +// collection tree. +// Unspecifies, references all collections in the link collection tree. +// +#define HIDP_LINK_COLLECTION_ROOT ((USHORT) -1) +#define HIDP_LINK_COLLECTION_UNSPECIFIED ((USHORT) 0) + + +typedef enum _HIDP_REPORT_TYPE +{ + HidP_Input, + HidP_Output, + HidP_Feature +} HIDP_REPORT_TYPE; + +typedef struct _USAGE_AND_PAGE +{ + USAGE Usage; + USAGE UsagePage; +} USAGE_AND_PAGE, *PUSAGE_AND_PAGE; + +#define HidP_IsSameUsageAndPage(u1, u2) ((* (PULONG) &u1) == (* (PULONG) &u2)) + +typedef struct _HIDP_BUTTON_CAPS +{ + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + + USHORT BitField; + USHORT LinkCollection; // A unique internal index pointer + + USAGE LinkUsage; + USAGE LinkUsagePage; + + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + + ULONG Reserved[10]; + union { + struct { + USAGE UsageMin, UsageMax; + USHORT StringMin, StringMax; + USHORT DesignatorMin, DesignatorMax; + USHORT DataIndexMin, DataIndexMax; + } Range; + struct { + USAGE Usage, Reserved1; + USHORT StringIndex, Reserved2; + USHORT DesignatorIndex, Reserved3; + USHORT DataIndex, Reserved4; + } NotRange; + }; + +} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS; + + +typedef struct _HIDP_VALUE_CAPS +{ + USAGE UsagePage; + UCHAR ReportID; + BOOLEAN IsAlias; + + USHORT BitField; + USHORT LinkCollection; // A unique internal index pointer + + USAGE LinkUsage; + USAGE LinkUsagePage; + + BOOLEAN IsRange; + BOOLEAN IsStringRange; + BOOLEAN IsDesignatorRange; + BOOLEAN IsAbsolute; + + BOOLEAN HasNull; // Does this channel have a null report union + UCHAR Reserved; + USHORT BitSize; // How many bits are devoted to this value? + + USHORT ReportCount; // See Note below. Usually set to 1. + USHORT Reserved2[5]; + + ULONG UnitsExp; + ULONG Units; + + LONG LogicalMin, LogicalMax; + LONG PhysicalMin, PhysicalMax; + + union { + struct { + USAGE UsageMin, UsageMax; + USHORT StringMin, StringMax; + USHORT DesignatorMin, DesignatorMax; + USHORT DataIndexMin, DataIndexMax; + } Range; + + struct { + USAGE Usage, Reserved1; + USHORT StringIndex, Reserved2; + USHORT DesignatorIndex, Reserved3; + USHORT DataIndex, Reserved4; + } NotRange; + }; +} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; + +// +// Notes: +// +// ReportCount: When a report descriptor declares an Input, Output, or +// Feature main item with fewer usage declarations than the report count, then +// the last usage applies to all remaining unspecified count in that main item. +// (As an example you might have data that required many fields to describe, +// possibly buffered bytes.) In this case, only one value cap structure is +// allocated for these associtated fields, all with the same usage, and Report +// Count reflects the number of fields involved. Normally ReportCount is 1. +// To access all of the fields in such a value structure would require using +// HidP_GetUsageValueArray and HidP_SetUsageValueArray. HidP_GetUsageValue/ +// HidP_SetScaledUsageValue will also work, however, these functions will only +// work with the first field of the structure. +// + +// +// The link collection tree consists of an array of LINK_COLLECTION_NODES +// where the index into this array is the same as the collection number. +// +// Given a collection A which contains a subcollection B, A is defined to be +// the parent B, and B is defined to be the child. +// +// Given collections A, B, and C where B and C are children of A, and B was +// encountered before C in the report descriptor, B is defined as a sibling of +// C. (This implies, of course, that if B is a sibling of C, then C is NOT a +// sibling of B). +// +// B is defined as the NextSibling of C if and only if there exists NO +// child collection of A, call it D, such that B is a sibling of D and D +// is a sibling of C. +// +// E is defined to be the FirstChild of A if and only if for all children of A, +// F, that are not equivalent to E, F is a sibling of E. +// (This implies, of course, that the does not exist a child of A, call it G, +// where E is a sibling of G). In other words the first sibling is the last +// link collection found in the list. +// +// In other words, if a collection B is defined within the definition of another +// collection A, B becomes a child of A. All collections with the same parent +// are considered siblings. The FirstChild of the parent collection, A, will be +// last collection defined that has A as a parent. The order of sibling pointers +// is similarly determined. When a collection B is defined, it becomes the +// FirstChild of it's parent collection. The previously defined FirstChild of the +// parent collection becomes the NextSibling of the new collection. As new +// collections with the same parent are discovered, the chain of sibling is built. +// +// With that in mind, the following describes conclusively a data structure +// that provides direct traversal up, down, and accross the link collection +// tree. +// +// +typedef struct _HIDP_LINK_COLLECTION_NODE +{ + USAGE LinkUsage; + USAGE LinkUsagePage; + USHORT Parent; + USHORT NumberOfChildren; + USHORT NextSibling; + USHORT FirstChild; + ULONG CollectionType: 8; // As defined in 6.2.2.6 of HID spec + ULONG IsAlias : 1; // This link node is an allias of the next link node. + ULONG Reserved: 23; + PVOID UserContext; // The user can hang his coat here. +} HIDP_LINK_COLLECTION_NODE, *PHIDP_LINK_COLLECTION_NODE; + +// +// When a link collection is described by a delimiter, alias link collection +// nodes are created. (One for each usage within the delimiter). +// The parser assigns each capability description listed above only one +// link collection. +// +// If a control is defined within a collection defined by +// delimited usages, then that control is said to be within multiple link +// collections, one for each usage within the open and close delimiter tokens. +// Such multiple link collecions are said to be aliases. The first N-1 such +// collections, listed in the link collection node array, have their IsAlias +// bit set. The last such link collection is the link collection index used +// in the capabilities described above. +// Clients wishing to set a control in an aliased collection, should walk the +// collection array once for each time they see the IsAlias flag set, and use +// the last link collection as the index for the below accessor functions. +// +// NB: if IsAlias is set, then NextSibling should be one more than the current +// link collection node index. +// + +typedef PUCHAR PHIDP_REPORT_DESCRIPTOR; +typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA; + +typedef struct _HIDP_CAPS +{ + USAGE Usage; + USAGE UsagePage; + USHORT InputReportByteLength; + USHORT OutputReportByteLength; + USHORT FeatureReportByteLength; + USHORT Reserved[17]; + + USHORT NumberLinkCollectionNodes; + + USHORT NumberInputButtonCaps; + USHORT NumberInputValueCaps; + USHORT NumberInputDataIndices; + + USHORT NumberOutputButtonCaps; + USHORT NumberOutputValueCaps; + USHORT NumberOutputDataIndices; + + USHORT NumberFeatureButtonCaps; + USHORT NumberFeatureValueCaps; + USHORT NumberFeatureDataIndices; +} HIDP_CAPS, *PHIDP_CAPS; + +typedef struct _HIDP_DATA +{ + USHORT DataIndex; + USHORT Reserved; + union { + ULONG RawValue; // for values + BOOLEAN On; // for buttons MUST BE TRUE for buttons. + }; +} HIDP_DATA, *PHIDP_DATA; +// +// The HIDP_DATA structure is used with HidP_GetData and HidP_SetData +// functions. +// +// The parser contiguously assigns every control (button or value) in a hid +// device a unique data index from zero to NumberXXXDataIndices -1 , inclusive. +// This value is found in the HIDP_BUTTON_CAPS and HIDP_VALUE_CAPS structures. +// +// Most clients will find the Get/Set Buttons / Value accessor functions +// sufficient to their needs, as they will allow the clients to access the +// data known to them while ignoring the other controls. +// +// More complex clients, which actually read the Button / Value Caps, and which +// do a value add service to these routines (EG Direct Input), will need to +// access all the data in the device without interest in the individual usage +// or link collection location. These are the clients that will find +// HidP_Data useful. +// + +typedef struct _HIDP_UNKNOWN_TOKEN +{ + UCHAR Token; + UCHAR Reserved[3]; + ULONG BitField; +} HIDP_UNKNOWN_TOKEN, *PHIDP_UNKNOWN_TOKEN; + +typedef struct _HIDP_EXTENDED_ATTRIBUTES +{ + UCHAR NumGlobalUnknowns; + UCHAR Reserved [3]; + PHIDP_UNKNOWN_TOKEN GlobalUnknowns; + // ... Additional attributes + ULONG Data [1]; // variableLength DO NOT ACCESS THIS FIELD +} HIDP_EXTENDED_ATTRIBUTES, *PHIDP_EXTENDED_ATTRIBUTES; + +NTSTATUS __stdcall +HidP_GetCaps ( + IN PHIDP_PREPARSED_DATA PreparsedData, + OUT PHIDP_CAPS Capabilities + ); +/*++ +Routine Description: + Returns a list of capabilities of a given hid device as described by its + preparsed data. + +Arguments: + PreparsedData The preparsed data returned from HIDCLASS. + Capabilities a HIDP_CAPS structure + +Return Value: +· HIDP_STATUS_SUCCESS +· HIDP_STATUS_INVALID_PREPARSED_DATA +--*/ + +NTSTATUS __stdcall +HidP_GetLinkCollectionNodes ( + OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, + IN OUT PULONG LinkCollectionNodesLength, + IN PHIDP_PREPARSED_DATA PreparsedData + ); +/*++ +Routine Description: + Return a list of PHIDP_LINK_COLLECTION_NODEs used to describe the link + collection tree of this hid device. See the above description of + struct _HIDP_LINK_COLLECTION_NODE. + +Arguments: + LinkCollectionNodes - a caller allocated array into which + HidP_GetLinkCollectionNodes will store the information + + LinKCollectionNodesLength - the caller sets this value to the length of the + the array in terms of number of elements. + HidP_GetLinkCollectionNodes sets this value to the actual + number of elements set. The total number of nodes required to + describe this HID device can be found in the + NumberLinkCollectionNodes field in the HIDP_CAPS structure. + +--*/ + +NTSTATUS __stdcall +HidP_GetButtonCaps ( + IN HIDP_REPORT_TYPE ReportType, + OUT PHIDP_BUTTON_CAPS ButtonCaps, + IN OUT PUSHORT ButtonCapsLength, + IN PHIDP_PREPARSED_DATA PreparsedData +); +#define HidP_GetButtonCaps(_Type_, _Caps_, _Len_, _Data_) \ + HidP_GetSpecificButtonCaps (_Type_, 0, 0, 0, _Caps_, _Len_, _Data_) +NTSTATUS __stdcall +HidP_GetSpecificButtonCaps ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, // Optional (0 => ignore) + IN USHORT LinkCollection, // Optional (0 => ignore) + IN USAGE Usage, // Optional (0 => ignore) + OUT PHIDP_BUTTON_CAPS ButtonCaps, + IN OUT PUSHORT ButtonCapsLength, + IN PHIDP_PREPARSED_DATA PreparsedData + ); +/*++ +Description: + HidP_GetButtonCaps returns all the buttons (binary values) that are a part + of the given report type for the Hid device represented by the given + preparsed data. + +Parameters: + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + UsagePage A usage page value used to limit the button caps returned to + those on a given usage page. If set to 0, this parameter is + ignored. Can be used with LinkCollection and Usage parameters + to further limit the number of button caps structures returned. + + LinkCollection HIDP_LINK_COLLECTION node array index used to limit the + button caps returned to those buttons in a given link + collection. If set to 0, this parameter is + ignored. Can be used with UsagePage and Usage parameters + to further limit the number of button caps structures + returned. + + Usage A usage value used to limit the button caps returned to those + with the specified usage value. If set to 0, this parameter + is ignored. Can be used with LinkCollection and UsagePage + parameters to further limit the number of button caps + structures returned. + + ButtonCaps A _HIDP_BUTTON_CAPS array containing information about all the + binary values in the given report. This buffer is provided by + the caller. + + ButtonLength As input, this parameter specifies the length of the + ButtonCaps parameter (array) in number of array elements. + As output, this value is set to indicate how many of those + array elements were filled in by the function. The maximum number of + button caps that can be returned is found in the HIDP_CAPS + structure. If HIDP_STATUS_BUFFER_TOO_SMALL is returned, + this value contains the number of array elements needed to + successfully complete the request. + + PreparsedData The preparsed data returned from HIDCLASS. + + +Return Value +HidP_GetSpecificButtonCaps returns the following error codes: +· HIDP_STATUS_SUCCESS. +· HIDP_STATUS_INVALID_REPORT_TYPE +· HIDP_STATUS_INVALID_PREPARSED_DATA +· HIDP_STATUS_BUFFER_TOO_SMALL (all given entries however have been filled in) +· HIDP_STATUS_USAGE_NOT_FOUND +--*/ + +NTSTATUS __stdcall +HidP_GetValueCaps ( + IN HIDP_REPORT_TYPE ReportType, + OUT PHIDP_VALUE_CAPS ValueCaps, + IN OUT PUSHORT ValueCapsLength, + IN PHIDP_PREPARSED_DATA PreparsedData +); +#define HidP_GetValueCaps(_Type_, _Caps_, _Len_, _Data_) \ + HidP_GetSpecificValueCaps (_Type_, 0, 0, 0, _Caps_, _Len_, _Data_) +NTSTATUS __stdcall +HidP_GetSpecificValueCaps ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, // Optional (0 => ignore) + IN USHORT LinkCollection, // Optional (0 => ignore) + IN USAGE Usage, // Optional (0 => ignore) + OUT PHIDP_VALUE_CAPS ValueCaps, + IN OUT PUSHORT ValueCapsLength, + IN PHIDP_PREPARSED_DATA PreparsedData + ); +/*++ +Description: + HidP_GetValueCaps returns all the values (non-binary) that are a part + of the given report type for the Hid device represented by the given + preparsed data. + +Parameters: + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + UsagePage A usage page value used to limit the value caps returned to + those on a given usage page. If set to 0, this parameter is + ignored. Can be used with LinkCollection and Usage parameters + to further limit the number of value caps structures returned. + + LinkCollection HIDP_LINK_COLLECTION node array index used to limit the + value caps returned to those buttons in a given link + collection. If set to 0, this parameter is + ignored. Can be used with UsagePage and Usage parameters + to further limit the number of value caps structures + returned. + + Usage A usage value used to limit the value caps returned to those + with the specified usage value. If set to 0, this parameter + is ignored. Can be used with LinkCollection and UsagePage + parameters to further limit the number of value caps + structures returned. + + ValueCaps A _HIDP_VALUE_CAPS array containing information about all the + non-binary values in the given report. This buffer is provided + by the caller. + + ValueLength As input, this parameter specifies the length of the ValueCaps + parameter (array) in number of array elements. As output, + this value is set to indicate how many of those array elements + were filled in by the function. The maximum number of + value caps that can be returned is found in the HIDP_CAPS + structure. If HIDP_STATUS_BUFFER_TOO_SMALL is returned, + this value contains the number of array elements needed to + successfully complete the request. + + PreparsedData The preparsed data returned from HIDCLASS. + + +Return Value +HidP_GetValueCaps returns the following error codes: +· HIDP_STATUS_SUCCESS. +· HIDP_STATUS_INVALID_REPORT_TYPE +· HIDP_STATUS_INVALID_PREPARSED_DATA +· HIDP_STATUS_BUFFER_TOO_SMALL (all given entries however have been filled in) +· HIDP_STATUS_USAGE_NOT_FOUND + +--*/ + +NTSTATUS __stdcall +HidP_GetExtendedAttributes ( + IN HIDP_REPORT_TYPE ReportType, + IN USHORT DataIndex, + IN PHIDP_PREPARSED_DATA PreparsedData, + OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, + IN OUT PULONG LengthAttributes + ); +/*++ +Description: + Given a data index from the value or button capabilities of a given control + return any extended attributes for the control if any exist. + +Parameters: + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + DataIndex The data index for the given control, found in the capabilities + structure for that control + + PreparsedData The preparsed data returned from HIDCLASS. + + Attributes Pointer to a buffer into which the extended attribute data will + be copied. + + LengthAttributes Length of the given buffer in bytes. + +Return Value + HIDP_STATUS_SUCCESS + HIDP_STATUS_DATA_INDEX_NOT_FOUND +--*/ + +NTSTATUS __stdcall +HidP_InitializeReportForID ( + IN HIDP_REPORT_TYPE ReportType, + IN UCHAR ReportID, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + + Initialize a report based on the given report ID. + +Parameters: + + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + PreparasedData Preparsed data structure returned by HIDCLASS + + Report Buffer which to set the data into. + + ReportLength Length of Report...Report should be at least as long as the + value indicated in the HIDP_CAPS structure for the device and + the corresponding ReportType + +Return Value + +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal + to the length specified in HIDP_CAPS + structure for the given ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType + +--*/ + +NTSTATUS __stdcall +HidP_SetData ( + IN HIDP_REPORT_TYPE ReportType, + IN PHIDP_DATA DataList, + IN OUT PULONG DataLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + + Please Note: Since usage value arrays deal with multiple fields for + for one usage value, they cannot be used with HidP_SetData + and HidP_GetData. In this case, + HIDP_STATUS_IS_USAGE_VALUE_ARRAY will be returned. + +Parameters: + + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + DataList Array of HIDP_DATA structures that contains the data values + that are to be set into the given report + + DataLength As input, length in array elements of DataList. As output, + contains the number of data elements set on successful + completion or an index into the DataList array to identify + the faulting HIDP_DATA value if an error code is returned. + + PreparasedData Preparsed data structure returned by HIDCLASS + + Report Buffer which to set the data into. + + ReportLength Length of Report...Report should be at least as long as the + value indicated in the HIDP_CAPS structure for the device and + the corresponding ReportType + +Return Value + HidP_SetData returns the following error codes. The report packet will + have all the data set up until the HIDP_DATA structure that caused the + error. DataLength, in the error case, will return this problem index. + +· HIDP_STATUS_SUCCESS -- upon successful insertion of all data + into the report packet. +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_DATA_INDEX_NOT_FOUND -- if a HIDP_DATA structure referenced a + data index that does not exist for this + device's ReportType +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal + to the length specified in HIDP_CAPS + structure for the given ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_IS_USAGE_VALUE_ARRAY -- if one of the HIDP_DATA structures + references a usage value array. + DataLength will contain the index into + the array that was invalid +· HIDP_STATUS_BUTTON_NOT_PRESSED -- if a HIDP_DATA structure attempted + to unset a button that was not already + set in the Report +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- a HIDP_DATA structure was found with + a valid index value but is contained + in a different report than the one + currently being processed +· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough entries in + a given Main Array Item to report all + buttons that have been requested to be + set +--*/ + +NTSTATUS __stdcall +HidP_GetData ( + IN HIDP_REPORT_TYPE ReportType, + OUT PHIDP_DATA DataList, + IN OUT PULONG DataLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + + Please Note: For obvious reasons HidP_SetData and HidP_GetData will not + access UsageValueArrays. + +Parameters: + ReportType One of HidP_Input, HidP_Output, or HidP_Feature. + + DataList Array of HIDP_DATA structures that will receive the data + values that are set in the given report + + DataLength As input, length in array elements of DataList. As output, + contains the number of data elements that were successfully + set by HidP_GetData. The maximum size necessary for DataList + can be determined by calling HidP_MaxDataListLength + + PreparasedData Preparsed data structure returned by HIDCLASS + + Report Buffer which to set the data into. + + ReportLength Length of Report...Report should be at least as long as the + value indicated in the HIDP_CAPS structure for the device and + the corresponding ReportType + +Return Value + HidP_GetData returns the following error codes. + +· HIDP_STATUS_SUCCESS -- upon successful retrieval of all data + from the report packet. +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal + to the length specified in HIDP_CAPS + structure for the given ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough array entries in + DataList to store all the indice values + in the given report. DataLength will + contain the number of array entries + required to hold all data +--*/ + +ULONG __stdcall +HidP_MaxDataListLength ( + IN HIDP_REPORT_TYPE ReportType, + IN PHIDP_PREPARSED_DATA PreparsedData + ); +/*++ +Routine Description: + + This function returns the maximum length of HIDP_DATA elements that + HidP_GetData could return for the given report type. + +Parameters: + + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + PreparsedData Preparsed data structure returned by HIDCLASS + +Return Value: + + The length of the data list array required for the HidP_GetData function + call. If an error occurs (either HIDP_STATUS_INVALID_REPORT_TYPE or + HIDP_STATUS_INVALID_PREPARSED_DATA), this function returns 0. + +--*/ + +#define HidP_SetButtons(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) \ + HidP_SetUsages(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) + +NTSTATUS __stdcall +HidP_SetUsages ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN PUSAGE UsageList, + IN OUT PULONG UsageLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + This function sets binary values (buttons) in a report. Given an + initialized packet of correct length, it modifies the report packet so that + each element in the given list of usages has been set in the report packet. + For example, in an output report with 5 LED’s, each with a given usage, + an application could turn on any subset of these lights by placing their + usages in any order into the usage array (UsageList). HidP_SetUsages would, + in turn, set the appropriate bit or add the corresponding byte into the + HID Main Array Item. + + A properly initialized Report packet is one of the correct byte length, + and all zeros. + + NOTE: A packet that has already been set with a call to a HidP_Set routine + can also be passed in. This routine then sets processes the UsageList + in the same fashion but verifies that the ReportID already set in + Report matches the report ID for the given usages. + +Parameters: + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + UsagePage All of the usages in the usage array, which HidP_SetUsages will + set in the report, refer to this same usage page. + If a client wishes to set usages in a report for multiple + usage pages then that client needs to make multiple calls to + HidP_SetUsages for each of the usage pages. + + UsageList A usage array containing the usages that HidP_SetUsages will set in + the report packet. + + UsageLength The length of the given usage array in array elements. + The parser will set this value to the position in the usage + array where it stopped processing. If successful, UsageLength + will be unchanged. In any error condition, this parameter + reflects how many of the usages in the usage list have + actually been set by the parser. This is useful for finding + the usage in the list which caused the error. + + PreparsedData The preparsed data recevied from HIDCLASS + + Report The report packet. + + ReportLength Length of the given report packet...Must be equal to the + value reported in the HIDP_CAPS structure for the device + and corresponding report type. + +Return Value + HidP_SetUsages returns the following error codes. On error, the report packet + will be correct up until the usage element that caused the error. + +· HIDP_STATUS_SUCCESS -- upon successful insertion of all usages + into the report packet. +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if a usage was found that exists in a + different report. If the report is + zero-initialized on entry the first + usage in the list will determine which + report ID is used. Otherwise, the + parser will verify that usage matches + the passed in report's ID +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage does not exist for any + report (no matter what the report ID) + for the given report type. +· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough entries in a + given Main Array Item to list all of + the given usages. The caller needs + to split his request into more than + one call +--*/ + +#define HidP_UnsetButtons(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) \ + HidP_UnsetUsages(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) + +NTSTATUS __stdcall +HidP_UnsetUsages ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN PUSAGE UsageList, + IN OUT PULONG UsageLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + This function unsets (turns off) binary values (buttons) in the report. Given + an initialized packet of correct length, it modifies the report packet so + that each element in the given list of usages has been unset in the + report packet. + + This function is the "undo" operation for SetUsages. If the given usage + is not already set in the Report, it will return an error code of + HIDP_STATUS_BUTTON_NOT_PRESSED. If the button is pressed, HidP_UnsetUsages + will unset the appropriate bit or remove the corresponding index value from + the HID Main Array Item. + + A properly initialized Report packet is one of the correct byte length, + and all zeros.. + + NOTE: A packet that has already been set with a call to a HidP_Set routine + can also be passed in. This routine then processes the UsageList + in the same fashion but verifies that the ReportID already set in + Report matches the report ID for the given usages. + +Parameters: + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + UsagePage All of the usages in the usage array, which HidP_UnsetUsages will + unset in the report, refer to this same usage page. + If a client wishes to unset usages in a report for multiple + usage pages then that client needs to make multiple calls to + HidP_UnsetUsages for each of the usage pages. + + UsageList A usage array containing the usages that HidP_UnsetUsages will + unset in the report packet. + + UsageLength The length of the given usage array in array elements. + The parser will set this value to the position in the usage + array where it stopped processing. If successful, UsageLength + will be unchanged. In any error condition, this parameter + reflects how many of the usages in the usage list have + actually been unset by the parser. This is useful for finding + the usage in the list which caused the error. + + PreparsedData The preparsed data recevied from HIDCLASS + + Report The report packet. + + ReportLength Length of the given report packet...Must be equal to the + value reported in the HIDP_CAPS structure for the device + and corresponding report type. + +Return Value + HidP_UnsetUsages returns the following error codes. On error, the report + packet will be correct up until the usage element that caused the error. + +· HIDP_STATUS_SUCCESS -- upon successful "unsetting" of all usages + in the report packet. +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if a usage was found that exists in a + different report. If the report is + zero-initialized on entry the first + usage in the list will determine which + report ID is used. Otherwise, the + parser will verify that usage matches + the passed in report's ID +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage does not exist for any + report (no matter what the report ID) + for the given report type. +· HIDP_STATUS_BUTTON_NOT_PRESSED -- if a usage corresponds to a button that + is not already set in the given report +--*/ + +#define HidP_GetButtons(Rty, UPa, LCo, ULi, ULe, Ppd, Rep, RLe) \ + HidP_GetUsages(Rty, UPa, LCo, ULi, ULe, Ppd, Rep, RLe) + +NTSTATUS __stdcall +HidP_GetUsages ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + OUT USAGE * UsageList, + IN OUT ULONG * UsageLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); +/*++ + +Routine Description: + This function returns the binary values (buttons) that are set in a HID + report. Given a report packet of correct length, it searches the report + packet for each usage for the given usage page and returns them in the + usage list. + +Parameters: + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + UsagePage All of the usages in the usage list, which HidP_GetUsages will + retrieve in the report, refer to this same usage page. + If the client wishes to get usages in a packet for multiple + usage pages then that client needs to make multiple calls + to HidP_GetUsages. + + LinkCollection An optional value which can limit which usages are returned + in the UsageList to those usages that exist in a specific + LinkCollection. A non-zero value indicates the index into + the HIDP_LINK_COLLECITON_NODE list returned by + HidP_GetLinkCollectionNodes of the link collection the + usage should belong to. A value of 0 indicates this + should value be ignored. + + UsageList The usage array that will contain all the usages found in + the report packet. + + UsageLength The length of the given usage array in array elements. + On input, this value describes the length of the usage list. + On output, HidP_GetUsages sets this value to the number of + usages that was found. Use HidP_MaxUsageListLength to + determine the maximum length needed to return all the usages + that a given report packet may contain. + + PreparsedData Preparsed data structure returned by HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet + + +Return Value + HidP_GetUsages returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully retrieving all the + usages from the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_BUFFER_TOO_SMALL -- if the UsageList is not big enough to + hold all the usages found in the report + packet. If this is returned, the buffer + will contain UsageLength number of + usages. Use HidP_MaxUsageListLength to + find the maximum length needed +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if no usages were found but usages + that match the UsagePage and + LinkCollection specified could be found + in a report with a different report ID +· HIDP_STATUS_USAGE_NOT_FOUND -- if there are no usages in a reports for + the device and ReportType that match the + UsagePage and LinkCollection that were + specified +--*/ + +#define HidP_GetButtonsEx(Rty, LCo, BLi, ULe, Ppd, Rep, RLe) \ + HidP_GetUsagesEx(Rty, LCo, BLi, ULe, Ppd, Rep, RLe) + +NTSTATUS __stdcall +HidP_GetUsagesEx ( + IN HIDP_REPORT_TYPE ReportType, + IN USHORT LinkCollection, // Optional + OUT PUSAGE_AND_PAGE ButtonList, + IN OUT ULONG * UsageLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); + +/*++ + +Routine Description: + This function returns the binary values (buttons) in a HID report. + Given a report packet of correct length, it searches the report packet + for all buttons and returns the UsagePage and Usage for each of the buttons + it finds. + +Parameters: + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + LinkCollection An optional value which can limit which usages are returned + in the ButtonList to those usages that exist in a specific + LinkCollection. A non-zero value indicates the index into + the HIDP_LINK_COLLECITON_NODE list returned by + HidP_GetLinkCollectionNodes of the link collection the + usage should belong to. A value of 0 indicates this + should value be ignored. + + ButtonList An array of USAGE_AND_PAGE structures describing all the + buttons currently ``down'' in the device. + + UsageLength The length of the given array in terms of elements. + On input, this value describes the length of the list. On + output, HidP_GetUsagesEx sets this value to the number of + usages that were found. Use HidP_MaxUsageListLength to + determine the maximum length needed to return all the usages + that a given report packet may contain. + + PreparsedData Preparsed data returned by HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value + HidP_GetUsagesEx returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully retrieving all the + usages from the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_BUFFER_TOO_SMALL -- if ButtonList is not big enough to + hold all the usages found in the report + packet. If this is returned, the buffer + will contain UsageLength number of + usages. Use HidP_MaxUsageListLength to + find the maximum length needed +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if no usages were found but usages + that match the specified LinkCollection + exist in report with a different report + ID. +· HIDP_STATUS_USAGE_NOT_FOUND -- if there are no usages in any reports that + match the LinkCollection parameter +--*/ + +#define HidP_GetButtonListLength(RTy, UPa, Ppd) \ + HidP_GetUsageListLength(Rty, UPa, Ppd) + +ULONG __stdcall +HidP_MaxUsageListLength ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, // Optional + IN PHIDP_PREPARSED_DATA PreparsedData + ); +/*++ +Routine Description: + This function returns the maximum number of usages that a call to + HidP_GetUsages or HidP_GetUsagesEx could return for a given HID report. + If calling for number of usages returned by HidP_GetUsagesEx, use 0 as + the UsagePage value. + +Parameters: + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + UsagePage Specifies the optional UsagePage to query for. If 0, will + return all the maximum number of usage values that could be + returned for a given ReportType. If non-zero, will return + the maximum number of usages that would be returned for the + ReportType with the given UsagePage. + + PreparsedData Preparsed data returned from HIDCLASS + +Return Value: + The length of the usage list array required for the HidP_GetUsages or + HidP_GetUsagesEx function call. If an error occurs (such as + HIDP_STATUS_INVALID_REPORT_TYPE or HIDP_INVALID_PREPARSED_DATA, this + returns 0. +--*/ + +NTSTATUS __stdcall +HidP_SetUsageValue ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + IN ULONG UsageValue, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); +/*++ +Description: + HidP_SetUsageValue inserts a value into the HID Report Packet in the field + corresponding to the given usage page and usage. HidP_SetUsageValue + casts this value to the appropriate bit length. If a report packet + contains two different fields with the same Usage and UsagePage, + they can be distinguished with the optional LinkCollection field value. + Using this function sets the raw value into the report packet with + no checking done as to whether it actually falls within the logical + minimum/logical maximum range. Use HidP_SetScaledUsageValue for this... + + NOTE: Although the UsageValue parameter is a ULONG, any casting that is + done will preserve or sign-extend the value. The value being set + should be considered a LONG value and will be treated as such by + this function. + +Parameters: + + ReportType One of HidP_Output or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will set the first field + it finds that matches the usage page and + usage. + + Usage The usage whose value HidP_SetUsageValue will set. + + UsageValue The raw value to set in the report buffer. This value must be within + the logical range or if a NULL value this value should be the + most negative value that can be represented by the number of bits + for this field. + + PreparsedData The preparsed data returned for HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value: + HidP_SetUsageValue returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully setting the value + in the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call HidP_SetUsageValue + again with a zero-initizialed report + packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + +NTSTATUS __stdcall +HidP_SetScaledUsageValue ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + IN LONG UsageValue, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN OUT PCHAR Report, + IN ULONG ReportLength + ); + +/*++ +Description: + HidP_SetScaledUsageValue inserts the UsageValue into the HID report packet + in the field corresponding to the given usage page and usage. If a report + packet contains two different fields with the same Usage and UsagePage, + they can be distinguished with the optional LinkCollection field value. + + If the specified field has a defined physical range, this function converts + the physical value specified to the corresponding logical value for the + report. If a physical value does not exist, the function will verify that + the value specified falls within the logical range and set according. + + If the range checking fails but the field has NULL values, the function will + set the field to the defined NULL value (most negative number possible) and + return HIDP_STATUS_NULL. In other words, use this function to set NULL + values for a given field by passing in a value that falls outside the + physical range if it is defined or the logical range otherwise. + + If the field does not support NULL values, an out of range error will be + returned instead. + +Parameters: + + ReportType One of HidP_Output or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will set the first field + it finds that matches the usage page and + usage. + + Usage The usage whose value HidP_SetScaledUsageValue will set. + + UsageValue The value to set in the report buffer. See the routine + description above for the different interpretations of this + value + + PreparsedData The preparsed data returned from HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value: + HidP_SetScaledUsageValue returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully setting the value + in the report packet +· HIDP_STATUS_NULL -- upon successfully setting the value + in the report packet as a NULL value +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_VALUE_OUT_OF_RANGE -- if the value specified failed to fall + within the physical range if it exists + or within the logical range otherwise + and the field specified by the usage + does not allow NULL values +· HIDP_STATUS_BAD_LOG_PHY_VALUES -- if the field has a physical range but + either the logical range is invalid + (max <= min) or the physical range is + invalid +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call + HidP_SetScaledUsageValue again with + a zero-initialized report packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + +NTSTATUS __stdcall +HidP_SetUsageValueArray ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + IN PCHAR UsageValue, + IN USHORT UsageValueByteLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + OUT PCHAR Report, + IN ULONG ReportLength + ); + +/*++ +Routine Descripton: + A usage value array occurs when the last usage in the list of usages + describing a main item must be repeated because there are less usages defined + than there are report counts declared for the given main item. In this case + a single value cap is allocated for that usage and the report count of that + value cap is set to reflect the number of fields to which that usage refers. + + HidP_SetUsageValueArray sets the raw bits for that usage which spans + more than one field in a report. + + NOTE: This function currently does not support value arrays where the + ReportSize for each of the fields in the array is not a multiple + of 8 bits. + + The UsageValue buffer should have the values set as they would appear + in the report buffer. If this function supported non 8-bit multiples + for the ReportSize then caller should format the input buffer so that + each new value begins at the bit immediately following the last bit + of the previous value + +Parameters: + + ReportType One of HidP_Output or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will set the first field + it finds that matches the usage page and + usage. + + Usage The usage whose value array HidP_SetUsageValueArray will set. + + UsageValue The buffer with the values to set into the value array. + The number of BITS required is found by multiplying the + BitSize and ReportCount fields of the Value Cap for this + control. The least significant bit of this control found in the + given report will be placed in the least significan bit location + of the array given (little-endian format), regardless of whether + or not the field is byte alligned or if the BitSize is a multiple + of sizeof (CHAR). + + See the above note for current implementation limitations. + + UsageValueByteLength Length of the UsageValue buffer (in bytes) + + PreparsedData The preparsed data returned from HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value: +· HIDP_STATUS_SUCCESS -- upon successfully setting the value + array in the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_NOT_VALUE_ARRAY -- if the control specified is not a + value array -- a value array will have + a ReportCount field in the + HIDP_VALUE_CAPS structure that is > 1 + Use HidP_SetUsageValue instead +· HIDP_STATUS_BUFFER_TOO_SMALL -- if the size of the passed in buffer with + the values to set is too small (ie. has + fewer values than the number of fields in + the array +· HIDP_STATUS_NOT_IMPLEMENTED -- if the usage value array has field sizes + that are not multiples of 8 bits, this + error code is returned since the function + currently does not handle setting into + such arrays. +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call + HidP_SetUsageValueArray again with + a zero-initialized report packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + + +NTSTATUS __stdcall +HidP_GetUsageValue ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + OUT PULONG UsageValue, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); + +/* +Description + HidP_GetUsageValue retrieves the value from the HID Report for the usage + specified by the combination of usage page, usage and link collection. + If a report packet contains two different fields with the same + Usage and UsagePage, they can be distinguished with the optional + LinkCollection field value. + +Parameters: + + ReportType One of HidP_Input or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will set the first field + it finds that matches the usage page and + usage. + + Usage The usage whose value HidP_GetUsageValue will retrieve + + UsageValue The raw value that is set for the specified field in the report + buffer. This value will either fall within the logical range + or if NULL values are allowed, a number outside the range to + indicate a NULL + + PreparsedData The preparsed data returned for HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value: + HidP_GetUsageValue returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value + from the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device + for the given ReportType +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call HidP_GetUsageValue + again with a different report packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + + +NTSTATUS __stdcall +HidP_GetScaledUsageValue ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + OUT PLONG UsageValue, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); + +/*++ +Description + HidP_GetScaledUsageValue retrieves a UsageValue from the HID report packet + in the field corresponding to the given usage page and usage. If a report + packet contains two different fields with the same Usage and UsagePage, + they can be distinguished with the optional LinkCollection field value. + + If the specified field has a defined physical range, this function converts + the logical value that exists in the report packet to the corresponding + physical value. If a physical range does not exist, the function will + return the logical value. This function will check to verify that the + logical value in the report falls within the declared logical range. + + When doing the conversion between logical and physical values, this + function assumes a linear extrapolation between the physical max/min and + the logical max/min. (Where logical is the values reported by the device + and physical is the value returned by this function). If the data field + size is less than 32 bits, then HidP_GetScaledUsageValue will sign extend + the value to 32 bits. + + If the range checking fails but the field has NULL values, the function + will set UsageValue to 0 and return HIDP_STATUS_NULL. Otherwise, it + returns a HIDP_STATUS_OUT_OF_RANGE error. + +Parameters: + + ReportType One of HidP_Output or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will retrieve the first + field it finds that matches the usage page + and usage. + + Usage The usage whose value HidP_GetScaledUsageValue will retrieve + + UsageValue The value retrieved from the report buffer. See the routine + description above for the different interpretations of this + value + + PreparsedData The preparsed data returned from HIDCLASS + + Report The report packet. + + ReportLength Length (in bytes) of the given report packet. + + +Return Value: + HidP_GetScaledUsageValue returns the following error codes: + +· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value + from the report packet +· HIDP_STATUS_NULL -- if the report packet had a NULL value + set +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_VALUE_OUT_OF_RANGE -- if the value retrieved from the packet + falls outside the logical range and + the field does not support NULL values +· HIDP_STATUS_BAD_LOG_PHY_VALUES -- if the field has a physical range but + either the logical range is invalid + (max <= min) or the physical range is + invalid +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call + HidP_GetScaledUsageValue with a + different report packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + +NTSTATUS __stdcall +HidP_GetUsageValueArray ( + IN HIDP_REPORT_TYPE ReportType, + IN USAGE UsagePage, + IN USHORT LinkCollection, // Optional + IN USAGE Usage, + OUT PCHAR UsageValue, + IN USHORT UsageValueByteLength, + IN PHIDP_PREPARSED_DATA PreparsedData, + IN PCHAR Report, + IN ULONG ReportLength + ); + +/*++ +Routine Descripton: + A usage value array occurs when the last usage in the list of usages + describing a main item must be repeated because there are less usages defined + than there are report counts declared for the given main item. In this case + a single value cap is allocated for that usage and the report count of that + value cap is set to reflect the number of fields to which that usage refers. + + HidP_GetUsageValueArray returns the raw bits for that usage which spans + more than one field in a report. + + NOTE: This function currently does not support value arrays where the + ReportSize for each of the fields in the array is not a multiple + of 8 bits. + + The UsageValue buffer will have the raw values as they are set + in the report packet. + +Parameters: + + ReportType One of HidP_Input, HidP_Output or HidP_Feature. + + UsagePage The usage page to which the given usage refers. + + LinkCollection (Optional) This value can be used to differentiate + between two fields that may have the same + UsagePage and Usage but exist in different + collections. If the link collection value + is zero, this function will set the first field + it finds that matches the usage page and + usage. + + Usage The usage whose value HidP_GetUsageValueArray will retreive. + + UsageValue A pointer to an array of characters where the value will be + placed. The number of BITS required is found by multiplying the + BitSize and ReportCount fields of the Value Cap for this + control. The least significant bit of this control found in the + given report will be placed in the least significant bit location + of the buffer (little-endian format), regardless of whether + or not the field is byte aligned or if the BitSize is a multiple + of sizeof (CHAR). + + See note above about current implementation limitations + + UsageValueByteLength + the length of the given UsageValue buffer. + + PreparsedData The preparsed data returned by the HIDCLASS + + Report The report packet. + + ReportLength Length of the given report packet. + +Return Value: + +· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value + from the report packet +· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. +· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid +· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not + equal to the length specified in + the HIDP_CAPS structure for the given + ReportType +· HIDP_STATUS_NOT_VALUE_ARRAY -- if the control specified is not a + value array -- a value array will have + a ReportCount field in the + HIDP_VALUE_CAPS structure that is > 1 + Use HidP_GetUsageValue instead +· HIDP_STATUS_BUFFER_TOO_SMALL -- if the size of the passed in buffer in + which to return the array is too small + (ie. has fewer values than the number of + fields in the array +· HIDP_STATUS_NOT_IMPLEMENTED -- if the usage value array has field sizes + that are not multiples of 8 bits, this + error code is returned since the function + currently does not handle getting values + from such arrays. +· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and + link collection exist but exists in + a report with a different report ID + than the report being passed in. To + set this value, call + HidP_GetUsageValueArray with a + different report packet +· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link + collection combination does not exist + in any reports for this ReportType +--*/ + +NTSTATUS __stdcall +HidP_UsageListDifference ( + IN PUSAGE PreviousUsageList, + IN PUSAGE CurrentUsageList, + OUT PUSAGE BreakUsageList, + OUT PUSAGE MakeUsageList, + IN ULONG UsageListLength + ); +/*++ +Routine Description: + This function will return the difference between a two lists of usages + (as might be returned from HidP_GetUsages), In other words, it will return + return a list of usages that are in the current list but not the previous + list as well as a list of usages that are in the previous list but not + the current list. + +Parameters: + + PreviousUsageList The list of usages before. + CurrentUsageList The list of usages now. + BreakUsageList Previous - Current. + MakeUsageList Current - Previous. + UsageListLength Represents the length of the usage lists in array + elements. If comparing two lists with a differing + number of array elements, this value should be + the size of the larger of the two lists. Any + zero found with a list indicates an early termination + of the list and any usages found after the first zero + will be ignored. +--*/ + +NTSTATUS __stdcall +HidP_UsageAndPageListDifference ( + IN PUSAGE_AND_PAGE PreviousUsageList, + IN PUSAGE_AND_PAGE CurrentUsageList, + OUT PUSAGE_AND_PAGE BreakUsageList, + OUT PUSAGE_AND_PAGE MakeUsageList, + IN ULONG UsageListLength + ); + +// +// Produce Make or Break Codes +// +typedef enum _HIDP_KEYBOARD_DIRECTION { + HidP_Keyboard_Break, + HidP_Keyboard_Make +} HIDP_KEYBOARD_DIRECTION; + +// +// A bitmap of the current shift state of the keyboard when using the +// below keyboard usages to i8042 translation function. +// +typedef struct _HIDP_KEYBOARD_MODIFIER_STATE { + union { + struct { + ULONG LeftControl: 1; + ULONG LeftShift: 1; + ULONG LeftAlt: 1; + ULONG LeftGUI: 1; + ULONG RightControl: 1; + ULONG RightShift: 1; + ULONG RightAlt: 1; + ULONG RigthGUI: 1; + ULONG CapsLock: 1; + ULONG ScollLock: 1; + ULONG NumLock: 1; + ULONG Reserved: 21; + }; + ULONG ul; + }; + +} HIDP_KEYBOARD_MODIFIER_STATE, * PHIDP_KEYBOARD_MODIFIER_STATE; + +// +// A call back function to give the i8042 scan codes to the caller of +// the below translation function. +// +typedef BOOLEAN (* PHIDP_INSERT_SCANCODES) ( + IN PVOID Context, // Some caller supplied context. + IN PCHAR NewScanCodes, // A list of i8042 scan codes. + IN ULONG Length // the length of the scan codes. + ); + +NTSTATUS __stdcall +HidP_TranslateUsageAndPagesToI8042ScanCodes ( + IN PUSAGE_AND_PAGE ChangedUsageList, + IN ULONG UsageListLength, + IN HIDP_KEYBOARD_DIRECTION KeyAction, + IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, + IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, + IN PVOID InsertCodesContext + ); +/*++ +Routine Description: +Parameters: +--*/ + +NTSTATUS __stdcall +HidP_TranslateUsagesToI8042ScanCodes ( + IN PUSAGE ChangedUsageList, + IN ULONG UsageListLength, + IN HIDP_KEYBOARD_DIRECTION KeyAction, + IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, + IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, + IN PVOID InsertCodesContext + ); +/*++ +Routine Description: +Parameters: +--*/ + + + +// +// Define NT Status codes with Facility Code of FACILITY_HID_ERROR_CODE +// + +// FACILITY_HID_ERROR_CODE defined in ntstatus.h +#ifndef FACILITY_HID_ERROR_CODE +#define FACILITY_HID_ERROR_CODE 0x11 +#endif + +#define HIDP_ERROR_CODES(SEV, CODE) \ + ((NTSTATUS) (((SEV) << 28) | (FACILITY_HID_ERROR_CODE << 16) | (CODE))) + +#define HIDP_STATUS_SUCCESS (HIDP_ERROR_CODES(0x0,0)) +#define HIDP_STATUS_NULL (HIDP_ERROR_CODES(0x8,1)) +#define HIDP_STATUS_INVALID_PREPARSED_DATA (HIDP_ERROR_CODES(0xC,1)) +#define HIDP_STATUS_INVALID_REPORT_TYPE (HIDP_ERROR_CODES(0xC,2)) +#define HIDP_STATUS_INVALID_REPORT_LENGTH (HIDP_ERROR_CODES(0xC,3)) +#define HIDP_STATUS_USAGE_NOT_FOUND (HIDP_ERROR_CODES(0xC,4)) +#define HIDP_STATUS_VALUE_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,5)) +#define HIDP_STATUS_BAD_LOG_PHY_VALUES (HIDP_ERROR_CODES(0xC,6)) +#define HIDP_STATUS_BUFFER_TOO_SMALL (HIDP_ERROR_CODES(0xC,7)) +#define HIDP_STATUS_INTERNAL_ERROR (HIDP_ERROR_CODES(0xC,8)) +#define HIDP_STATUS_I8042_TRANS_UNKNOWN (HIDP_ERROR_CODES(0xC,9)) +#define HIDP_STATUS_INCOMPATIBLE_REPORT_ID (HIDP_ERROR_CODES(0xC,0xA)) +#define HIDP_STATUS_NOT_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xB)) +#define HIDP_STATUS_IS_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xC)) +#define HIDP_STATUS_DATA_INDEX_NOT_FOUND (HIDP_ERROR_CODES(0xC,0xD)) +#define HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,0xE)) +#define HIDP_STATUS_BUTTON_NOT_PRESSED (HIDP_ERROR_CODES(0xC,0xF)) +#define HIDP_STATUS_REPORT_DOES_NOT_EXIST (HIDP_ERROR_CODES(0xC,0x10)) +#define HIDP_STATUS_NOT_IMPLEMENTED (HIDP_ERROR_CODES(0xC,0x20)) + +// +// We blundered this status code. +// +#define HIDP_STATUS_I8242_TRANS_UNKNOWN HIDP_STATUS_I8042_TRANS_UNKNOWN + +#include + +#endif diff --git a/client/include/hidsdi.h b/client/include/hidsdi.h new file mode 100644 index 00000000..d0db806b --- /dev/null +++ b/client/include/hidsdi.h @@ -0,0 +1,412 @@ +/*++ + +Copyright (c) 1996 Microsoft Corporation + +Module Name: + + HIDSDI.H + +Abstract: + + This module contains the PUBLIC definitions for the + code that implements the HID dll. + +Environment: + + Kernel & user mode + +--*/ + + +#ifndef _HIDSDI_H +#define _HIDSDI_H + +#include + +//#include "wtypes.h" + +//#include +//#include +//#include + +typedef LONG NTSTATUS; +#include "hidusage.h" +#include "hidpi.h" + +typedef struct _HIDD_CONFIGURATION { + PVOID cookie; + ULONG size; + ULONG RingBufferSize; +} HIDD_CONFIGURATION, *PHIDD_CONFIGURATION; + +typedef struct _HIDD_ATTRIBUTES { + ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES) + + // + // Vendor ids of this hid device + // + USHORT VendorID; + USHORT ProductID; + USHORT VersionNumber; + + // + // Additional fields will be added to the end of this structure. + // +} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; + + +BOOLEAN __stdcall +HidD_GetAttributes ( + IN HANDLE HidDeviceObject, + OUT PHIDD_ATTRIBUTES Attributes + ); +/*++ +Routine Description: + Fill in the given HIDD_ATTRIBUTES structure with the attributes of the + given hid device. + +--*/ + + +void __stdcall +HidD_GetHidGuid ( + OUT LPGUID HidGuid + ); + +BOOLEAN __stdcall +HidD_GetPreparsedData ( + IN HANDLE HidDeviceObject, + OUT PHIDP_PREPARSED_DATA * PreparsedData + ); +/*++ +Routine Description: + Given a handle to a valid Hid Class Device Object, retrieve the preparsed + data for the device. This routine will allocate the appropriately + sized buffer to hold this preparsed data. It is up to client to call + HidP_FreePreparsedData to free the memory allocated to this structure when + it is no longer needed. + +Arguments: + HidDeviceObject A handle to a Hid Device that the client obtains using + a call to CreateFile on a valid Hid device string name. + The string name can be obtained using standard PnP calls. + + PreparsedData An opaque data structure used by other functions in this + library to retrieve information about a given device. + +Return Value: + TRUE if successful. + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_FreePreparsedData ( + IN PHIDP_PREPARSED_DATA PreparsedData + ); + +BOOLEAN __stdcall +HidD_FlushQueue ( + IN HANDLE HidDeviceObject + ); +/*++ +Routine Description: + Flush the input queue for the given HID device. + +Arguments: + HidDeviceObject A handle to a Hid Device that the client obtains using + a call to CreateFile on a valid Hid device string name. + The string name can be obtained using standard PnP calls. + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetConfiguration ( + IN HANDLE HidDeviceObject, + OUT PHIDD_CONFIGURATION Configuration, + IN ULONG ConfigurationLength + ); +/*++ +Routine Description: + Get the configuration information for this Hid device + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Configuration A configuration structure. HidD_GetConfiguration MUST + be called before the configuration can be modified and + set using HidD_SetConfiguration + + ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this + parameter, we can later increase the length of the + configuration array and not break older apps. + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_SetConfiguration ( + IN HANDLE HidDeviceObject, + IN PHIDD_CONFIGURATION Configuration, + IN ULONG ConfigurationLength + ); +/*++ +Routine Description: + Set the configuration information for this Hid device... + + NOTE: HidD_GetConfiguration must be called to retrieve the current + configuration information before this information can be modified + and set. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Configuration A configuration structure. HidD_GetConfiguration MUST + be called before the configuration can be modified and + set using HidD_SetConfiguration + + ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this + parameter, we can later increase the length of the + configuration array and not break older apps. + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetFeature ( + IN HANDLE HidDeviceObject, + OUT PVOID ReportBuffer, + IN ULONG ReportBufferLength + ); +/*++ +Routine Description: + Retrieve a feature report from a HID device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + ReportBuffer The buffer that the feature report should be placed + into. The first byte of the buffer should be set to + the report ID of the desired report + + ReportBufferLength The size (in bytes) of ReportBuffer. This value + should be greater than or equal to the + FeatureReportByteLength field as specified in the + HIDP_CAPS structure for the device +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_SetFeature ( + IN HANDLE HidDeviceObject, + IN PVOID ReportBuffer, + IN ULONG ReportBufferLength + ); +/*++ +Routine Description: + Send a feature report to a HID device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + ReportBuffer The buffer of the feature report to send to the device + + ReportBufferLength The size (in bytes) of ReportBuffer. This value + should be greater than or equal to the + FeatureReportByteLength field as specified in the + HIDP_CAPS structure for the device +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetNumInputBuffers ( + IN HANDLE HidDeviceObject, + OUT PULONG NumberBuffers + ); +/*++ +Routine Description: + This function returns the number of input buffers used by the specified + file handle to the Hid device. Each file object has a number of buffers + associated with it to queue reports read from the device but which have + not yet been read by the user-mode app with a handle to that device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + NumberBuffers Number of buffers currently being used for this file + handle to the Hid device + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_SetNumInputBuffers ( + IN HANDLE HidDeviceObject, + OUT ULONG NumberBuffers + ); +/*++ + +Routine Description: + This function sets the number of input buffers used by the specified + file handle to the Hid device. Each file object has a number of buffers + associated with it to queue reports read from the device but which have + not yet been read by the user-mode app with a handle to that device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + NumberBuffers New number of buffers to use for this file handle to + the Hid device + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetPhysicalDescriptor ( + IN HANDLE HidDeviceObject, + OUT PVOID Buffer, + IN ULONG BufferLength + ); +/*++ +Routine Description: + This function retrieves the raw physical descriptor for the specified + Hid device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Buffer Buffer which on return will contain the physical + descriptor if one exists for the specified device + handle + + BufferLength Length of buffer (in bytes) + + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetManufacturerString ( + IN HANDLE HidDeviceObject, + OUT PVOID Buffer, + IN ULONG BufferLength + ); +/*++ +Routine Description: + This function retrieves the manufacturer string from the specified + Hid device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Buffer Buffer which on return will contain the manufacturer + string returned from the device. This string is a + wide-character string + + BufferLength Length of Buffer (in bytes) + + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetProductString ( + IN HANDLE HidDeviceObject, + OUT PVOID Buffer, + IN ULONG BufferLength + ); +/*++ +Routine Description: + This function retrieves the product string from the specified + Hid device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Buffer Buffer which on return will contain the product + string returned from the device. This string is a + wide-character string + + BufferLength Length of Buffer (in bytes) + + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetIndexedString ( + IN HANDLE HidDeviceObject, + IN ULONG StringIndex, + OUT PVOID Buffer, + IN ULONG BufferLength + ); +/*++ +Routine Description: + This function retrieves a string from the specified Hid device that is + specified with a certain string index. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + StringIndex Index of the string to retrieve + + Buffer Buffer which on return will contain the product + string returned from the device. This string is a + wide-character string + + BufferLength Length of Buffer (in bytes) + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + +BOOLEAN __stdcall +HidD_GetSerialNumberString ( + IN HANDLE HidDeviceObject, + OUT PVOID Buffer, + IN ULONG BufferLength + ); +/*++ +Routine Description: + This function retrieves the serial number string from the specified + Hid device. + +Arguments: + HidDeviceObject A handle to a Hid Device Object. + + Buffer Buffer which on return will contain the serial number + string returned from the device. This string is a + wide-character string + + BufferLength Length of Buffer (in bytes) + +Return Value: + TRUE if successful + FALSE otherwise -- Use GetLastError() to get extended error information +--*/ + + +#include + +#endif diff --git a/client/include/hidusage.h b/client/include/hidusage.h new file mode 100644 index 00000000..4ea9dd12 --- /dev/null +++ b/client/include/hidusage.h @@ -0,0 +1,263 @@ +/*++ + +Copyright (c) 1996, 1997 Microsoft Corporation + +Module Name: + + HIDUSAGE.H + +Abstract: + + Public Definitions of HID USAGES. + +Environment: + + Kernel & user mode + +--*/ + +#ifndef __HIDUSAGE_H__ +#define __HIDUSAGE_H__ + +// +// Usage Pages +// + +typedef USHORT USAGE, *PUSAGE; + +#define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01) +#define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02) +#define HID_USAGE_PAGE_VR ((USAGE) 0x03) +#define HID_USAGE_PAGE_SPORT ((USAGE) 0x04) +#define HID_USAGE_PAGE_GAME ((USAGE) 0x05) +#define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07) +#define HID_USAGE_PAGE_LED ((USAGE) 0x08) +#define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09) +#define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A) +#define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B) +#define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C) +#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D) +#define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10) +#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14) + + +// +// Usages from Generic Desktop Page (0x01) +// + +#define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01) +#define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02) +#define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04) +#define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05) +#define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06) +#define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07) +#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80) + +#define HID_USAGE_GENERIC_X ((USAGE) 0x30) +#define HID_USAGE_GENERIC_Y ((USAGE) 0x31) +#define HID_USAGE_GENERIC_Z ((USAGE) 0x32) +#define HID_USAGE_GENERIC_RX ((USAGE) 0x33) +#define HID_USAGE_GENERIC_RY ((USAGE) 0x34) +#define HID_USAGE_GENERIC_RZ ((USAGE) 0x35) +#define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36) +#define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37) +#define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38) +#define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39) +#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A) +#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B) +#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C) +#define HID_USAGE_GENERIC_VX ((USAGE) 0x40) +#define HID_USAGE_GENERIC_VY ((USAGE) 0x41) +#define HID_USAGE_GENERIC_VZ ((USAGE) 0x42) +#define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43) +#define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44) +#define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45) +#define HID_USAGE_GENERIC_VNO ((USAGE) 0x46) +#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81) +#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82) +#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83) +#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84) +#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85) +#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86) +#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87) +#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88) +#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89) +#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A) +#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B) +#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C) +#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D) + +// +// Usages from Simulation Controls Page (0x02) +// + +#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA) +#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB) + +// +// Virtual Reality Controls Page (0x03) +// + + +// +// Sport Controls Page (0x04) +// + + +// +// Game Controls Page (0x05) +// + + +// +// Keyboard/Keypad Page (0x07) +// + + // Error "keys" +#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00) +#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01) +#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02) +#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03) + + // Letters +#define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04) +#define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D) + // Numbers +#define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E) +#define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27) + // Modifier Keys +#define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0) +#define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1) +#define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2) +#define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3) +#define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4) +#define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5) +#define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6) +#define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7) +#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47) +#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53) +#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39) + // Funtion keys +#define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A) +#define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45) + +#define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28) +#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29) +#define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A) + +#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46) + +// and hundreds more... + +// +// LED Page (0x08) +// + +#define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01) +#define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02) +#define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03) +#define HID_USAGE_LED_COMPOSE ((USAGE) 0x04) +#define HID_USAGE_LED_KANA ((USAGE) 0x05) +#define HID_USAGE_LED_POWER ((USAGE) 0x06) +#define HID_USAGE_LED_SHIFT ((USAGE) 0x07) +#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08) +#define HID_USAGE_LED_MUTE ((USAGE) 0x09) +#define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A) +#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B) +#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C) +#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D) +#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E) +#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F) +#define HID_USAGE_LED_REPEAT ((USAGE) 0x10) +#define HID_USAGE_LED_STEREO ((USAGE) 0x11) +#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12) +#define HID_USAGE_LED_SPINNING ((USAGE) 0x13) +#define HID_USAGE_LED_CAV ((USAGE) 0x14) +#define HID_USAGE_LED_CLV ((USAGE) 0x15) +#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16) +#define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17) +#define HID_USAGE_LED_RING ((USAGE) 0x18) +#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19) +#define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A) +#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B) +#define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C) +#define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D) +#define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E) +#define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F) +#define HID_USAGE_LED_HOLD ((USAGE) 0x20) +#define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21) +#define HID_USAGE_LED_COVERAGE ((USAGE) 0x22) +#define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23) +#define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24) +#define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25) +#define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26) +#define HID_USAGE_LED_STAND_BY ((USAGE) 0x27) +#define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28) +#define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29) +#define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A) +#define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B) +#define HID_USAGE_LED_BUSY ((USAGE) 0x2C) +#define HID_USAGE_LED_READY ((USAGE) 0x2D) +#define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E) +#define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F) +#define HID_USAGE_LED_REMOTE ((USAGE) 0x30) +#define HID_USAGE_LED_FORWARD ((USAGE) 0x31) +#define HID_USAGE_LED_REVERSE ((USAGE) 0x32) +#define HID_USAGE_LED_STOP ((USAGE) 0x33) +#define HID_USAGE_LED_REWIND ((USAGE) 0x34) +#define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35) +#define HID_USAGE_LED_PLAY ((USAGE) 0x36) +#define HID_USAGE_LED_PAUSE ((USAGE) 0x37) +#define HID_USAGE_LED_RECORD ((USAGE) 0x38) +#define HID_USAGE_LED_ERROR ((USAGE) 0x39) +#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A) +#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B) +#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C) +#define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D) +#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E) +#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F) +#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40) +#define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41) +#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42) +#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43) +#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44) +#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45) +#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46) +#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47) +#define HID_USAGE_LED_RED ((USAGE) 0x48) +#define HID_USAGE_LED_GREEN ((USAGE) 0x49) +#define HID_USAGE_LED_AMBER ((USAGE) 0x4A) +#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x3B) + +// +// Button Page (0x09) +// +// There is no need to label these usages. +// + + +// +// Ordinal Page (0x0A) +// +// There is no need to label these usages. +// + + +// +// Telephony Device Page (0x0B) +// + +#define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01) +#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02) +#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03) +#define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04) +#define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05) +#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06) +#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07) + +// +// and others... +// + + +#endif diff --git a/client/obj/.dummy b/client/obj/.dummy new file mode 100644 index 00000000..e69de29b diff --git a/client/prox.cpp b/client/prox.cpp new file mode 100644 index 00000000..4b80e3cc --- /dev/null +++ b/client/prox.cpp @@ -0,0 +1,580 @@ +#include +#include +#include +#include +#include +extern "C" { +#include "include/hidsdi.h" +#include "include/hidpi.h" +} + +#include "prox.h" + +#define OUR_VID 0x9ac4 +#define OUR_PID 0x4b8f +#define bzero(b,len) (memset((b), '\0', (len)), (void) 0) + +int offline = 0; +HANDLE UsbHandle; + +static void ShowError(void) +{ + char buf[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + buf, sizeof(buf), NULL); + printf("ERROR: %s", buf); +} + +static BOOL UsbConnect(void) +{ + typedef void (__stdcall *GetGuidProc)(GUID *); + typedef BOOLEAN (__stdcall *GetAttrProc)(HANDLE, HIDD_ATTRIBUTES *); + typedef BOOLEAN (__stdcall *GetPreparsedProc)(HANDLE, + PHIDP_PREPARSED_DATA *); + typedef NTSTATUS (__stdcall *GetCapsProc)(PHIDP_PREPARSED_DATA, PHIDP_CAPS); + GetGuidProc getGuid; + GetAttrProc getAttr; + GetPreparsedProc getPreparsed; + GetCapsProc getCaps; + + HMODULE h = LoadLibrary("hid.dll"); + getGuid = (GetGuidProc)GetProcAddress(h, "HidD_GetHidGuid"); + getAttr = (GetAttrProc)GetProcAddress(h, "HidD_GetAttributes"); + getPreparsed = (GetPreparsedProc)GetProcAddress(h, "HidD_GetPreparsedData"); + getCaps = (GetCapsProc)GetProcAddress(h, "HidP_GetCaps"); + + GUID hidGuid; + getGuid(&hidGuid); + + HDEVINFO devInfo; + devInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, + DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); + + SP_DEVICE_INTERFACE_DATA devInfoData; + devInfoData.cbSize = sizeof(devInfoData); + + int i; + for(i = 0;; i++) { + if(!SetupDiEnumDeviceInterfaces(devInfo, 0, &hidGuid, i, &devInfoData)) + { + if(GetLastError() != ERROR_NO_MORE_ITEMS) { +// printf("SetupDiEnumDeviceInterfaces failed\n"); + } +// printf("done list\n"); + SetupDiDestroyDeviceInfoList(devInfo); + return FALSE; + } + +// printf("item %d:\n", i); + + DWORD sizeReqd = 0; + if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData, + NULL, 0, &sizeReqd, NULL)) + { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { +// printf("SetupDiGetDeviceInterfaceDetail (0) failed\n"); + continue; + } + } + + SP_DEVICE_INTERFACE_DETAIL_DATA *devInfoDetailData = + (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(sizeReqd); + devInfoDetailData->cbSize = sizeof(*devInfoDetailData); + + if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData, + devInfoDetailData, 87, NULL, NULL)) + { +// printf("SetupDiGetDeviceInterfaceDetail (1) failed\n"); + continue; + } + + char *path = devInfoDetailData->DevicePath; + + UsbHandle = CreateFile(path, /*GENERIC_READ |*/ GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + + if(UsbHandle == INVALID_HANDLE_VALUE) { + ShowError(); +// printf("CreateFile failed: for '%s'\n", path); + continue; + } + + HIDD_ATTRIBUTES attr; + attr.Size = sizeof(attr); + if(!getAttr(UsbHandle, &attr)) { + ShowError(); +// printf("HidD_GetAttributes failed\n"); + continue; + } + +// printf("VID: %04x PID %04x\n", attr.VendorID, attr.ProductID); + + if(attr.VendorID != OUR_VID || attr.ProductID != OUR_PID) { + CloseHandle(UsbHandle); +// printf(" nope, not us\n"); + continue; + } + +// printf ("got it!\n"); + CloseHandle(UsbHandle); + + UsbHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + + if(UsbHandle == INVALID_HANDLE_VALUE) { + ShowError(); +// printf("Error, couldn't open our own handle as desired.\n"); + return FALSE; + } + + PHIDP_PREPARSED_DATA pp; + getPreparsed(UsbHandle, &pp); + HIDP_CAPS caps; + + if(getCaps(pp, &caps) != HIDP_STATUS_SUCCESS) { +// printf("getcaps failed\n"); + return FALSE; + } + +// printf("input/out report %d/%d\n", caps.InputReportByteLength, +// caps.OutputReportByteLength); + + + return TRUE; + } + return FALSE; +} + +BOOL ReceiveCommandPoll(UsbCommand *c) +{ + static BOOL ReadInProgress = FALSE; + static OVERLAPPED Ov; + static BYTE Buf[65]; + static DWORD HaveRead; + + if(!ReadInProgress) { + memset(&Ov, 0, sizeof(Ov)); + ReadFile(UsbHandle, Buf, 65, &HaveRead, &Ov); + if(GetLastError() != ERROR_IO_PENDING) { + ShowError(); + exit(-1); + } + ReadInProgress = TRUE; + } + + if(HasOverlappedIoCompleted(&Ov)) { + ReadInProgress = FALSE; + + if(!GetOverlappedResult(UsbHandle, &Ov, &HaveRead, FALSE)) { + ShowError(); + exit(-1); + } + + memcpy(c, Buf+1, 64); + + return TRUE; + } else { + return FALSE; + } +} + +void ReceiveCommand(UsbCommand *c) +{ + while(!ReceiveCommandPoll(c)) { + Sleep(0); + } +} + +void SendCommand(UsbCommand *c, BOOL wantAck) +{ + BYTE buf[65]; + buf[0] = 0; + memcpy(buf+1, c, 64); + + DWORD written; + OVERLAPPED ov; + + memset(&ov, 0, sizeof(ov)); + WriteFile(UsbHandle, buf, 65, &written, &ov); + if(GetLastError() != ERROR_IO_PENDING) { + ShowError(); + exit(-1); + } + + while(!HasOverlappedIoCompleted(&ov)) { + Sleep(0); + } + + if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) { + ShowError(); + exit(-1); + } + + if(wantAck) { + UsbCommand ack; + ReceiveCommand(&ack); + if(ack.cmd != CMD_ACK) { + printf("bad ACK\n"); + exit(-1); + } + } +} + +static DWORD ExpectedAddr; +static BYTE QueuedToSend[256]; +static BOOL AllWritten; +#define PHYSICAL_FLASH_START 0x100000 + +struct partition { + int start; + int end; + int precious; + const char *name; +}; +struct partition partitions[] = { + {0x100000, 0x102000, 1, "bootrom"}, + {0x102000, 0x110000, 0, "fpga"}, + {0x110000, 0x140000, 0, "os"}, +}; + +/* If translate is set, subtract PHYSICAL_FLASH_START to translate for old + * bootroms. + */ +static void FlushPrevious(int translate) +{ + UsbCommand c; + memset(&c, 0, sizeof(c)); + +// printf("expected = %08x flush, ", ExpectedAddr); + + int i; + for(i = 0; i < 240; i += 48) { + c.cmd = CMD_SETUP_WRITE; + memcpy(c.d.asBytes, QueuedToSend+i, 48); + c.ext1 = (i/4); + SendCommand(&c, TRUE); + } + + c.cmd = CMD_FINISH_WRITE; + c.ext1 = (ExpectedAddr-1) & (~255); + if(translate) { + c.ext1 -= PHYSICAL_FLASH_START; + } + printf("Flashing address: %08x\r", c.ext1); + memcpy(c.d.asBytes, QueuedToSend+240, 16); + SendCommand(&c, TRUE); + + AllWritten = TRUE; +} + +/* Where must be between start_addr (inclusive) and end_addr (exclusive). + */ +static void GotByte(int where, BYTE which, int start_addr, int end_addr, int translate) +{ + AllWritten = FALSE; + + if(where < start_addr || where >= end_addr) { + printf("bad: got byte at %08x, outside of range %08x-%08x\n", where, start_addr, end_addr); + exit(-1); + } + + if(where != ExpectedAddr) { + printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr); + exit(-1); + } + QueuedToSend[where & 255] = which; + ExpectedAddr++; + + if((where & 255) == 255) { + // we have completed a full page + FlushPrevious(translate); + } +} + +static int HexVal(int c) +{ + c = tolower(c); + if(c >= '0' && c <= '9') { + return c - '0'; + } else if(c >= 'a' && c <= 'f') { + return (c - 'a') + 10; + } else { + printf("bad hex digit '%c'\n", c); + exit(-1); + } +} + +static BYTE HexByte(char *s) +{ + return (HexVal(s[0]) << 4) | HexVal(s[1]); +} + +static void LoadFlashFromSRecords(const char *file, int start_addr, int end_addr, int translate) +{ + ExpectedAddr = start_addr; + + FILE *f = fopen(file, "r"); + if(!f) { + printf("couldn't open file\n"); + exit(-1); + } + + char line[512]; + while(fgets(line, sizeof(line), f)) { + if(memcmp(line, "S3", 2)==0) { + char *s = line + 2; + int len = HexByte(s) - 5; + s += 2; + + char addrStr[9]; + memcpy(addrStr, s, 8); + addrStr[8] = '\0'; + DWORD addr; + sscanf(addrStr, "%x", &addr); + s += 8; + + /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */ + if(addr < PHYSICAL_FLASH_START) + addr += PHYSICAL_FLASH_START; + + int i; + for(i = 0; i < len; i++) { + while((addr+i) > ExpectedAddr) { + GotByte(ExpectedAddr, 0xff, start_addr, end_addr, translate); + } + GotByte(addr+i, HexByte(s), start_addr, end_addr, translate); + s += 2; + } + } + } + + if(!AllWritten) FlushPrevious(translate); + + fclose(f); + printf("\ndone.\n"); +} + +static int PrepareFlash(struct partition *p, const char *filename, unsigned int state) +{ + int translate = 0; + if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { + UsbCommand c; + c.cmd = CMD_START_FLASH; + c.ext1 = p->start; + c.ext2 = p->end; + + /* Only send magic when flashing bootrom */ + if(p->precious) { + c.ext3 = START_FLASH_MAGIC; + } else { + c.ext3 = 0; + } + SendCommand(&c, TRUE); + translate = 0; + } 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"); + translate = 1; + } + + LoadFlashFromSRecords(filename, p->start, p->end, translate); + return 1; +} + +static unsigned int GetProxmarkState(void) +{ + unsigned int state = 0; + + UsbCommand c; + c.cmd = CMD_DEVICE_INFO; + SendCommand(&c, FALSE); + + 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.ext1; + break; + default: + fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); + exit(-1); + break; + } + +#if 0 + if(state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) printf("New bootrom present\n"); + if(state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) printf("New osimage present\n"); + if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) printf("Currently in bootrom\n"); + if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) printf("Currently in OS\n"); +#endif + + return state; +} + +static 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, FALSE); + 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, FALSE); + fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); + fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); + } + + + Sleep(1000); + + while(!UsbConnect()) { Sleep(1000); } + fprintf(stderr,"Found.\n"); + + return GetProxmarkState(); + } + + return 0; +} + +static void usage(char **argv) +{ + int i; + printf("Usage: %s gui\n", argv[0]); + printf(" %s offline\n", argv[0]); + printf(" %s areas file.s19\n", argv[0]); + printf(" Known areas are:"); + for(i=0; i<(sizeof(partitions)/sizeof(partitions[0])); i++) { + fprintf(stderr, " %s", partitions[i].name); + } + + printf("\n"); +} + +/* On first call, have *offset = -1, *length = 0; */ +static int find_next_area(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; +} + +int main(int argc, char **argv) +{ + int i = 0; + + if(argc < 2) { + usage(argv); + exit(-1); + } + + // Only do this if NOT in offline mode + if (strcmp(argv[1], "offline")) + { + for(;;) { + if(UsbConnect()) { + break; + } + if(i == 0) { + printf("...no device connected, polling for it now\n"); + } + if(i > 50000) { + printf("Could not connect to USB device; exiting.\n"); + return -1; + } + i++; + Sleep(5); + } + } + + if(strcmp(argv[1], "gui")==0) { + ShowGui(); + } else if(strcmp(argv[1], "offline")==0) { + offline = 1; + ShowGui(); + } + + /* 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); + } + + unsigned int state = EnterFlashState(); + + if( !(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) ) { + fprintf(stderr, "Proxmark would not enter flash state, abort\n"); + exit(-1); + } + + 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++; + } + + return 0; +} diff --git a/client/prox.h b/client/prox.h new file mode 100644 index 00000000..aeb6dfea --- /dev/null +++ b/client/prox.h @@ -0,0 +1,107 @@ +#ifndef __PROX_H +#define __PROX_H + +#include "../include/usb_cmd.h" + +// prox.cpp +void ReceiveCommand(UsbCommand *c); +BOOL ReceiveCommandPoll(UsbCommand *c); +void SendCommand(UsbCommand *c, BOOL wantAck); + +// gui.cpp +void ShowGui(); +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(BYTE *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 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 WORD Iso15693Crc(BYTE *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 new file mode 100644 index 00000000..7e87b582 --- /dev/null +++ b/client/proxgui.cpp @@ -0,0 +1,58 @@ +#include "proxgui.h" +#include "proxguiqt.h" + +static ProxGuiQT *gui = NULL; + +extern "C" void ShowGraphWindow(void) +{ + if (!gui) + return; + + gui->ShowGraphWindow(); +} + +extern "C" void HideGraphWindow(void) +{ + if (!gui) + return; + + gui->HideGraphWindow(); +} + +extern "C" void RepaintGraphWindow(void) +{ + if (!gui) + return; + + gui->RepaintGraphWindow(); +} + +extern "C" void MainGraphics(void) +{ + if (!gui) + return; + + gui->MainLoop(); +} + +extern "C" void InitGraphics(int argc, char **argv) +{ +#ifdef Q_WS_X11 + bool useGUI = getenv("DISPLAY") != 0; +#else + bool useGUI = true; +#endif + if (!useGUI) + return; + + gui = new ProxGuiQT(argc, argv); +} + +extern "C" void ExitGraphics(void) +{ + if (!gui) + return; + + delete gui; + gui = NULL; +} diff --git a/client/proxgui.h b/client/proxgui.h new file mode 100644 index 00000000..6989f541 --- /dev/null +++ b/client/proxgui.h @@ -0,0 +1,22 @@ +#ifdef __cplusplus +extern "C" { +#endif + +void ShowGraphWindow(void); +void HideGraphWindow(void); +void RepaintGraphWindow(void); +void MainGraphics(void); +void InitGraphics(int argc, char **argv); +void ExitGraphics(void); + +#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; + +#ifdef __cplusplus +} +#endif diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp new file mode 100644 index 00000000..70c64fbd --- /dev/null +++ b/client/proxguiqt.cpp @@ -0,0 +1,337 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proxguiqt.h" +#include "proxgui.h" + +void ProxGuiQT::ShowGraphWindow(void) +{ + emit ShowGraphWindowSignal(); +} + +void ProxGuiQT::RepaintGraphWindow(void) +{ + emit RepaintGraphWindowSignal(); +} + +void ProxGuiQT::HideGraphWindow(void) +{ + emit HideGraphWindowSignal(); +} + +void ProxGuiQT::_ShowGraphWindow(void) +{ + if(!plotapp) + return; + + if (!plotwidget) + plotwidget = new ProxWidget(); + + plotwidget->show(); +} + +void ProxGuiQT::_RepaintGraphWindow(void) +{ + if (!plotapp || !plotwidget) + return; + + plotwidget->update(); +} + +void ProxGuiQT::_HideGraphWindow(void) +{ + if (!plotapp || !plotwidget) + return; + + plotwidget->hide(); +} + +void ProxGuiQT::MainLoop() +{ + plotapp = new QApplication(argc, argv); + + connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); + connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); + connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); + + plotapp->exec(); +} + +ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), + argc(argc), argv(argv) +{ +} + +ProxGuiQT::~ProxGuiQT(void) +{ + if (plotwidget) { + delete plotwidget; + plotwidget = NULL; + } + + if (plotapp) { + plotapp->quit(); + delete plotapp; + plotapp = NULL; + } +} + +void ProxWidget::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + QPainterPath penPath, whitePath, greyPath, lightgreyPath, cursorAPath, cursorBPath; + QRect r; + QBrush brush(QColor(100, 255, 100)); + QPen pen(QColor(100, 255, 100)); + + painter.setFont(QFont("Arial", 10)); + + if(GraphStart < 0) { + GraphStart = 0; + } + + if (CursorAPos > GraphTraceLen) + CursorAPos= 0; + if(CursorBPos > GraphTraceLen) + CursorBPos= 0; + + r = rect(); + + painter.fillRect(r, QColor(0, 0, 0)); + + whitePath.moveTo(r.left() + 40, r.top()); + whitePath.lineTo(r.left() + 40, r.bottom()); + + int zeroHeight = r.top() + (r.bottom() - r.top()) / 2; + + greyPath.moveTo(r.left(), zeroHeight); + greyPath.lineTo(r.right(), zeroHeight); + painter.setPen(QColor(100, 100, 100)); + painter.drawPath(greyPath); + + // plot X and Y grid lines + int i; + if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) { + for(i = 40; i < r.right(); i += (int)(PlotGridX * GraphPixelsPerPoint)) { + //SelectObject(hdc, GreyPenLite); + //MoveToEx(hdc, r.left + i, r.top, NULL); + //LineTo(hdc, r.left + i, r.bottom); + lightgreyPath.moveTo(r.left()+i,r.top()); + lightgreyPath.lineTo(r.left()+i,r.bottom()); + painter.drawPath(lightgreyPath); + } + } + if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){ + for(i = 0; i < ((r.top() + r.bottom())>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) { + lightgreyPath.moveTo(r.left() + 40,zeroHeight + i); + lightgreyPath.lineTo(r.right(),zeroHeight + i); + painter.drawPath(lightgreyPath); + lightgreyPath.moveTo(r.left() + 40,zeroHeight - i); + lightgreyPath.lineTo(r.right(),zeroHeight - i); + painter.drawPath(lightgreyPath); + } + } + + int startMax = + (GraphTraceLen - (int)((r.right() - r.left() - 40) / GraphPixelsPerPoint)); + if(startMax < 0) { + startMax = 0; + } + if(GraphStart > startMax) { + GraphStart = startMax; + } + + int absYMax = 1; + + for(i = GraphStart; ; i++) { + if(i >= GraphTraceLen) { + break; + } + if(fabs((double)GraphBuffer[i]) > absYMax) { + absYMax = (int)fabs((double)GraphBuffer[i]); + } + int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); + if(x > r.right()) { + break; + } + } + + absYMax = (int)(absYMax*1.2 + 1); + + // number of points that will be plotted + int span = (int)((r.right() - r.left()) / GraphPixelsPerPoint); + // one label every 100 pixels, let us say + int labels = (r.right() - r.left() - 40) / 100; + if(labels <= 0) labels = 1; + int pointsPerLabel = span / labels; + if(pointsPerLabel <= 0) pointsPerLabel = 1; + + int yMin = INT_MAX; + int yMax = INT_MIN; + int yMean = 0; + int n = 0; + + for(i = GraphStart; ; i++) { + if(i >= GraphTraceLen) { + break; + } + int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); + if(x > r.right() + GraphPixelsPerPoint) { + break; + } + + int y = GraphBuffer[i]; + if(y < yMin) { + yMin = y; + } + if(y > yMax) { + yMax = y; + } + yMean += y; + n++; + + y = (y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight; + if(i == GraphStart) { + penPath.moveTo(x, y); + } else { + penPath.lineTo(x, y); + } + + if(GraphPixelsPerPoint > 10) { + QRect f(QPoint(x - 3, y - 3),QPoint(x + 3, y + 3)); + painter.fillRect(f, brush); + } + + if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) { + whitePath.moveTo(x, zeroHeight - 3); + whitePath.lineTo(x, zeroHeight + 3); + + char str[100]; + sprintf(str, "+%d", (i - GraphStart)); + + painter.setPen(QColor(255, 255, 255)); + QRect size; + QFontMetrics metrics(painter.font()); + size = metrics.boundingRect(str); + painter.drawText(x - (size.right() - size.left()), zeroHeight + 9, str); + + penPath.moveTo(x,y); + } + + if(i == CursorAPos || i == CursorBPos) { + QPainterPath *cursorPath; + + if(i == CursorAPos) { + cursorPath = &cursorAPath; + } else { + cursorPath = &cursorBPath; + } + cursorPath->moveTo(x, r.top()); + cursorPath->lineTo(x, r.bottom()); + penPath.moveTo(x, y); + } + } + + if(n != 0) { + yMean /= n; + } + + painter.setPen(QColor(255, 255, 255)); + painter.drawPath(whitePath); + painter.setPen(pen); + painter.drawPath(penPath); + painter.setPen(QColor(255, 255, 0)); + painter.drawPath(cursorAPath); + painter.setPen(QColor(255, 0, 255)); + painter.drawPath(cursorBPath); + + char str[100]; + sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]", + GraphStart, yMax, yMin, yMean, n, GraphTraceLen, + CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor,GraphPixelsPerPoint,CursorAPos,GraphBuffer[CursorAPos],CursorBPos,GraphBuffer[CursorBPos]); + + painter.setPen(QColor(255, 255, 255)); + painter.drawText(50, r.bottom() - 20, str); +} + +ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1) +{ + resize(600, 500); + + QPalette palette(QColor(0,0,0,0)); + palette.setColor(QPalette::WindowText, QColor(255,255,255)); + palette.setColor(QPalette::Text, QColor(255,255,255)); + palette.setColor(QPalette::Button, QColor(100, 100, 100)); + setPalette(palette); + setAutoFillBackground(true); +} + +void ProxWidget::closeEvent(QCloseEvent *event) +{ + event->ignore(); + this->hide(); +} + +void ProxWidget::mouseMoveEvent(QMouseEvent *event) +{ + int x = event->x(); + x -= 40; + x = (int)(x / GraphPixelsPerPoint); + x += GraphStart; + if((event->buttons() & Qt::LeftButton)) { + CursorAPos = x; + } else if (event->buttons() & Qt::RightButton) { + CursorBPos = x; + } + + + this->update(); +} + +void ProxWidget::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Down: + if(GraphPixelsPerPoint <= 50) { + GraphPixelsPerPoint *= 2; + } + break; + + case Qt::Key_Up: + if(GraphPixelsPerPoint >= 0.02) { + GraphPixelsPerPoint /= 2; + } + break; + + case Qt::Key_Right: + if(GraphPixelsPerPoint < 20) { + GraphStart += (int)(20 / GraphPixelsPerPoint); + } else { + GraphStart++; + } + break; + + case Qt::Key_Left: + if(GraphPixelsPerPoint < 20) { + GraphStart -= (int)(20 / GraphPixelsPerPoint); + } else { + GraphStart--; + } + break; + + default: + QWidget::keyPressEvent(event); + return; + break; + } + + this->update(); +} diff --git a/client/proxguiqt.h b/client/proxguiqt.h new file mode 100644 index 00000000..58ff8326 --- /dev/null +++ b/client/proxguiqt.h @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +class ProxWidget : public QWidget +{ + Q_OBJECT; + + private: + int GraphStart; + double GraphPixelsPerPoint; + int CursorAPos; + int CursorBPos; + + public: + ProxWidget(QWidget *parent = 0); + + protected: + void paintEvent(QPaintEvent *event); + void closeEvent(QCloseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); } + void keyPressEvent(QKeyEvent *event); +}; + +class ProxGuiQT : public QObject +{ + Q_OBJECT; + + private: + QApplication *plotapp; + ProxWidget *plotwidget; + int argc; + char **argv; + void (*main_func)(void); + + public: + ProxGuiQT(int argc, char **argv); + ~ProxGuiQT(void); + void ShowGraphWindow(void); + void RepaintGraphWindow(void); + void HideGraphWindow(void); + void MainLoop(void); + + private slots: + void _ShowGraphWindow(void); + void _RepaintGraphWindow(void); + void _HideGraphWindow(void); + + signals: + void ShowGraphWindowSignal(void); + void RepaintGraphWindowSignal(void); + void HideGraphWindowSignal(void); +}; diff --git a/client/proxmark3.c b/client/proxmark3.c new file mode 100644 index 00000000..3c3b7927 --- /dev/null +++ b/client/proxmark3.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "translate.h" +#include "prox.h" +#include "proxmark3.h" +#include "proxgui.h" + +struct usb_receiver_arg { + int run; +}; + +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 (ReceiveCommandP(&cmdbuf) > 0) { + int i; + + for (i=0; iusb_present == 1) { + pthread_create(&reader_thread, NULL, &usb_receiver, &rarg); + } + cmd = readline(PROXPROMPT); + rarg.run=0; + if (arg->usb_present == 1) { + pthread_join(reader_thread, NULL); + } + + if (cmd) { + if (cmd[0] != 0x00) { + CommandReceived(cmd); + add_history(cmd); + } + free(cmd); + } else { + printf("\n"); + break; + } + } + + 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; +} diff --git a/client/proxmark3.h b/client/proxmark3.h new file mode 100644 index 00000000..67d80841 --- /dev/null +++ b/client/proxmark3.h @@ -0,0 +1,14 @@ +#define PROXPROMPT "proxmark3> " + +#define FLASH_ADDR_OS 0x10000 +#define FLASH_ADDR_FPGA 0x2000 + +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); + +void setlogfilename(char *fn); diff --git a/client/snooper.c b/client/snooper.c new file mode 100644 index 00000000..9a92e84d --- /dev/null +++ b/client/snooper.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "translate.h" +#include "prox.h" +#include "proxmark3.h" + +#define HANDLE_ERROR if (error_occured) { \ + 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++) { + ReceiveCommandP(&cmdbuf); + } + HANDLE_ERROR + + CommandReceived("hi14alist"); + HANDLE_ERROR + } + } + + CloseProxmark(); + return 0; +} diff --git a/client/translate.h b/client/translate.h new file mode 100644 index 00000000..145268a0 --- /dev/null +++ b/client/translate.h @@ -0,0 +1,9 @@ +#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/unbind-proxmark b/client/unbind-proxmark new file mode 100755 index 00000000..986c0015 --- /dev/null +++ b/client/unbind-proxmark @@ -0,0 +1,16 @@ +#!/bin/sh + +for i in /sys/bus/usb/devices/*; do + if grep "9ac4" "${i}/idVendor" >/dev/null 2>&1; then + echo "Found Proxmark..." + dev=`basename "${i}"` + + for j in /sys/bus/usb/drivers/usbhid/*; do + if basename "${j}"|grep "^${dev}" >/dev/null; then + bound="`basename "${j}"`" + echo "Unbinding ${bound}..." + echo -n "${bound}" >/sys/bus/usb/drivers/usbhid/unbind + fi + done + fi +done diff --git a/client/usb.c b/client/usb.c new file mode 100644 index 00000000..c326aeca --- /dev/null +++ b/client/usb.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include + +#include "translate.h" +#include "prox.h" +#include "proxmark3.h" + +usb_dev_handle *devh = NULL; +static unsigned int claimed_iface = 0; +unsigned char return_on_error = 0; +unsigned char error_occured = 0; + +void SendCommand(UsbCommand *c, BOOL wantAck) { + int ret; + +#if 0 + printf("Sending %d bytes\n", sizeof(UsbCommand)); +#endif + 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; + } + + if(wantAck) { + UsbCommand ack; + ReceiveCommand(&ack); + if(ack.cmd != CMD_ACK) { + printf("bad ACK\n"); + exit(-1); + } + } +} + +int ReceiveCommandP(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 0; + + 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 0; + } + } else { + if (ret && (ret < sizeof(UsbCommand))) { + fprintf(stderr, "Read only %d instead of requested %d bytes!\n", + ret, (int)sizeof(UsbCommand)); + } + +#if 0 + { + int i; + + printf("Read %d bytes\n", ret); + for (i = 0; i < ret; i++) { + printf("0x%02X ", ((unsigned char*)c)[i]); + if (!((i+1)%8)) + printf("\n"); + } + printf("\n"); + } +#endif + } + + return ret; +} + +void ReceiveCommand(UsbCommand *c) { + while(ReceiveCommandP(c)<0) {} +} + +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/windows.h b/client/windows.h new file mode 100644 index 00000000..e69de29b diff --git a/linux/Makefile b/linux/Makefile deleted file mode 100644 index 70e7cc7a..00000000 --- a/linux/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -#COMMON_FLAGS = -m32 -LDLIBS = -L/usr/local/lib -lusb -lreadline -lpthread -LDFLAGS = $(COMMON_FLAGS) -CFLAGS = -I. -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) - -CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) - -ifneq ($(QTLDLIBS),) -QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o -CFLAGS += -DHAVE_GUI -MOC = $(shell type moc-qt4 >/dev/null 2>&1 && echo moc-qt4 || echo moc) -LINK.o = $(LINK.cpp) -else -QTGUI = guidummy.o -endif - -all: proxmark3 snooper cli flasher - -all-static: LDLIBS:=-static $(LDLIBS) -all-static: snooper cli flasher - -proxmark3: LDLIBS+=$(QTLDLIBS) -proxmark3: proxmark3.o gui.o command.o usb.o $(QTGUI) - -command.o: ../winsrc/command.cpp translate.h - -snooper: snooper.o gui.o command.o usb.o guidummy.o - -cli: cli.o gui.o command.o usb.o guidummy.o - -flasher: flasher.o usb.o - -proxguiqt.moc.cpp: proxguiqt.h - $(MOC) -o$@ $^ - -clean: - rm -f cli flasher proxmark3 snooper *.o *.moc.cpp - -.PHONY: all clean diff --git a/linux/cli.c b/linux/cli.c deleted file mode 100644 index e893a727..00000000 --- a/linux/cli.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "translate.h" -#include "../winsrc/prox.h" -#include "proxmark3.h" - -#define HANDLE_ERROR if (error_occured) { \ - 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++) { - ReceiveCommandP(&cmdbuf); - } - HANDLE_ERROR - - CommandReceived(argv[2]); - HANDLE_ERROR - } - } - - CloseProxmark(); - return 0; -} diff --git a/linux/command.c b/linux/command.c deleted file mode 100644 index 902045c6..00000000 --- a/linux/command.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "translate.h" -#include "../winsrc/command.cpp" diff --git a/linux/flasher.c b/linux/flasher.c deleted file mode 100644 index 8797becf..00000000 --- a/linux/flasher.c +++ /dev/null @@ -1,355 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "translate.h" -#include "../winsrc/prox.h" -#include "proxmark3.h" - -static DWORD ExpectedAddr; -static BYTE QueuedToSend[256]; -static BOOL AllWritten; -#define PHYSICAL_FLASH_START 0x100000 - -struct partition { - int start; - int end; - int precious; - const char *name; -}; -struct partition partitions[] = { - {0x100000, 0x102000, 1, "bootrom"}, - {0x102000, 0x110000, 0, "fpga"}, - {0x110000, 0x140000, 0, "os"}, -}; - -/* If translate is set, subtract PHYSICAL_FLASH_START to translate for old - * bootroms. - */ -static void FlushPrevious(int translate) -{ - UsbCommand c; - memset(&c, 0, sizeof(c)); - - printf("expected = %08x flush, ", ExpectedAddr); - - int i; - for(i = 0; i < 240; i += 48) { - c.cmd = CMD_SETUP_WRITE; - memcpy(c.d.asBytes, QueuedToSend+i, 48); - c.ext1 = (i/4); - SendCommand(&c, TRUE); - } - - c.cmd = CMD_FINISH_WRITE; - c.ext1 = (ExpectedAddr-1) & (~255); - if(translate) { - c.ext1 -= PHYSICAL_FLASH_START; - } - printf("c.ext1 = %08x\r", c.ext1); - memcpy(c.d.asBytes, QueuedToSend+240, 16); - SendCommand(&c, TRUE); - - AllWritten = TRUE; -} - -/* Where must be between start_addr (inclusive) and end_addr (exclusive). - */ -static void GotByte(DWORD where, BYTE which, int start_addr, int end_addr, int translate) -{ - AllWritten = FALSE; - - if(where < start_addr || where >= end_addr) { - printf("bad: got byte at %08x, outside of range %08x-%08x\n", where, start_addr, end_addr); - exit(-1); - } - - if(where != ExpectedAddr) { - printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr); - exit(-1); - } - QueuedToSend[where & 255] = which; - ExpectedAddr++; - - if((where & 255) == 255) { - // we have completed a full page - FlushPrevious(translate); - } -} - -static int HexVal(int c) -{ - c = tolower(c); - if(c >= '0' && c <= '9') { - return c - '0'; - } else if(c >= 'a' && c <= 'f') { - return (c - 'a') + 10; - } else { - printf("bad hex digit '%c'\n", c); - exit(-1); - } -} - -static BYTE HexByte(char *s) -{ - return (HexVal(s[0]) << 4) | HexVal(s[1]); -} - -static void LoadFlashFromSRecords(const char *file, int start_addr, int end_addr, int translate) -{ - ExpectedAddr = start_addr; - - FILE *f = fopen(file, "r"); - if(!f) { - printf("couldn't open file\n"); - exit(-1); - } - - char line[512]; - while(fgets(line, sizeof(line), f)) { - if(memcmp(line, "S3", 2)==0) { - char *s = line + 2; - int len = HexByte(s) - 5; - s += 2; - - char addrStr[9]; - memcpy(addrStr, s, 8); - addrStr[8] = '\0'; - DWORD addr; - sscanf(addrStr, "%x", &addr); - s += 8; - - /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */ - if(addr < PHYSICAL_FLASH_START) - addr += PHYSICAL_FLASH_START; - - int i; - for(i = 0; i < len; i++) { - while((addr+i) > ExpectedAddr) { - GotByte(ExpectedAddr, 0xff, start_addr, end_addr, translate); - } - GotByte(addr+i, HexByte(s), start_addr, end_addr, translate); - s += 2; - } - } - } - - if(!AllWritten) FlushPrevious(translate); - - fclose(f); - printf("\ndone.\n"); -} - -static int PrepareFlash(struct partition *p, const char *filename, unsigned int state) -{ - int translate = 0; - if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { - UsbCommand c; - c.cmd = CMD_START_FLASH; - c.ext1 = p->start; - c.ext2 = p->end; - - /* Only send magic when flashing bootrom */ - if(p->precious) { - c.ext3 = START_FLASH_MAGIC; - } else { - c.ext3 = 0; - } - SendCommand(&c, TRUE); - translate = 0; - } 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"); - translate = 1; - } - - LoadFlashFromSRecords(filename, p->start, p->end, translate); - return 1; -} - -static unsigned int GetProxmarkState(void) -{ - unsigned int state = 0; - - UsbCommand c; - c.cmd = CMD_DEVICE_INFO; - SendCommand(&c, FALSE); - - 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.ext1; - break; - default: - fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); - exit(-1); - break; - } - -#if 0 - if(state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) printf("New bootrom present\n"); - if(state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) printf("New osimage present\n"); - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) printf("Currently in bootrom\n"); - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) printf("Currently in OS\n"); -#endif - - return state; -} - -static 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, FALSE); - 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, FALSE); - fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); - fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); - } - - CloseProxmark(); - sleep(1); - - while(!(devh=OpenProxmark(0))) { sleep(1); } - fprintf(stderr,"Found.\n"); - - return GetProxmarkState(); - } - - return 0; -} - -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:"); - for(i=0; i<(sizeof(partitions)/sizeof(partitions[0])); 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.s19 path/to/fpgaimage.s19\n", argv[0]); -} - -/* On first call, have *offset = -1, *length = 0; */ -static 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; -} - -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(!(devh=OpenProxmark(0))) { sleep(1); } - fprintf(stderr,"Found.\n"); - - unsigned int state = EnterFlashState(); - - if( !(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) ) { - fprintf(stderr, "Proxmark would not enter flash state, abort\n"); - exit(-1); - } - - 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++; - } - - UsbCommand c; - bzero(&c, sizeof(c)); - c.cmd = CMD_HARDWARE_RESET; - SendCommand(&c, FALSE); - - CloseProxmark(); - - fprintf(stderr,"Have a nice day!\n"); - - return 0; -} diff --git a/linux/gui.c b/linux/gui.c deleted file mode 100644 index d31c5287..00000000 --- a/linux/gui.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -#include "proxgui.h" -#include "translate.h" -#include "../winsrc/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/linux/guidummy.c b/linux/guidummy.c deleted file mode 100644 index 39bcc756..00000000 --- a/linux/guidummy.c +++ /dev/null @@ -1,17 +0,0 @@ -#include - -void ShowGraphWindow(void) -{ - static int warned = 0; - - if (!warned) { - printf("No GUI in this build!\n"); - warned = 1; - } -} - -void HideGraphWindow(void) {} -void RepaintGraphWindow(void) {} -void MainGraphics() {} -void InitGraphics(int argc, char **argv) {} -void ExitGraphics(void) {} diff --git a/linux/proxgui.cpp b/linux/proxgui.cpp deleted file mode 100644 index 7e87b582..00000000 --- a/linux/proxgui.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "proxgui.h" -#include "proxguiqt.h" - -static ProxGuiQT *gui = NULL; - -extern "C" void ShowGraphWindow(void) -{ - if (!gui) - return; - - gui->ShowGraphWindow(); -} - -extern "C" void HideGraphWindow(void) -{ - if (!gui) - return; - - gui->HideGraphWindow(); -} - -extern "C" void RepaintGraphWindow(void) -{ - if (!gui) - return; - - gui->RepaintGraphWindow(); -} - -extern "C" void MainGraphics(void) -{ - if (!gui) - return; - - gui->MainLoop(); -} - -extern "C" void InitGraphics(int argc, char **argv) -{ -#ifdef Q_WS_X11 - bool useGUI = getenv("DISPLAY") != 0; -#else - bool useGUI = true; -#endif - if (!useGUI) - return; - - gui = new ProxGuiQT(argc, argv); -} - -extern "C" void ExitGraphics(void) -{ - if (!gui) - return; - - delete gui; - gui = NULL; -} diff --git a/linux/proxgui.h b/linux/proxgui.h deleted file mode 100644 index 6989f541..00000000 --- a/linux/proxgui.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - -void ShowGraphWindow(void); -void HideGraphWindow(void); -void RepaintGraphWindow(void); -void MainGraphics(void); -void InitGraphics(int argc, char **argv); -void ExitGraphics(void); - -#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; - -#ifdef __cplusplus -} -#endif diff --git a/linux/proxguiqt.cpp b/linux/proxguiqt.cpp deleted file mode 100644 index 70c64fbd..00000000 --- a/linux/proxguiqt.cpp +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "proxguiqt.h" -#include "proxgui.h" - -void ProxGuiQT::ShowGraphWindow(void) -{ - emit ShowGraphWindowSignal(); -} - -void ProxGuiQT::RepaintGraphWindow(void) -{ - emit RepaintGraphWindowSignal(); -} - -void ProxGuiQT::HideGraphWindow(void) -{ - emit HideGraphWindowSignal(); -} - -void ProxGuiQT::_ShowGraphWindow(void) -{ - if(!plotapp) - return; - - if (!plotwidget) - plotwidget = new ProxWidget(); - - plotwidget->show(); -} - -void ProxGuiQT::_RepaintGraphWindow(void) -{ - if (!plotapp || !plotwidget) - return; - - plotwidget->update(); -} - -void ProxGuiQT::_HideGraphWindow(void) -{ - if (!plotapp || !plotwidget) - return; - - plotwidget->hide(); -} - -void ProxGuiQT::MainLoop() -{ - plotapp = new QApplication(argc, argv); - - connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow())); - connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow())); - connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow())); - - plotapp->exec(); -} - -ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL), - argc(argc), argv(argv) -{ -} - -ProxGuiQT::~ProxGuiQT(void) -{ - if (plotwidget) { - delete plotwidget; - plotwidget = NULL; - } - - if (plotapp) { - plotapp->quit(); - delete plotapp; - plotapp = NULL; - } -} - -void ProxWidget::paintEvent(QPaintEvent *event) -{ - QPainter painter(this); - QPainterPath penPath, whitePath, greyPath, lightgreyPath, cursorAPath, cursorBPath; - QRect r; - QBrush brush(QColor(100, 255, 100)); - QPen pen(QColor(100, 255, 100)); - - painter.setFont(QFont("Arial", 10)); - - if(GraphStart < 0) { - GraphStart = 0; - } - - if (CursorAPos > GraphTraceLen) - CursorAPos= 0; - if(CursorBPos > GraphTraceLen) - CursorBPos= 0; - - r = rect(); - - painter.fillRect(r, QColor(0, 0, 0)); - - whitePath.moveTo(r.left() + 40, r.top()); - whitePath.lineTo(r.left() + 40, r.bottom()); - - int zeroHeight = r.top() + (r.bottom() - r.top()) / 2; - - greyPath.moveTo(r.left(), zeroHeight); - greyPath.lineTo(r.right(), zeroHeight); - painter.setPen(QColor(100, 100, 100)); - painter.drawPath(greyPath); - - // plot X and Y grid lines - int i; - if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) { - for(i = 40; i < r.right(); i += (int)(PlotGridX * GraphPixelsPerPoint)) { - //SelectObject(hdc, GreyPenLite); - //MoveToEx(hdc, r.left + i, r.top, NULL); - //LineTo(hdc, r.left + i, r.bottom); - lightgreyPath.moveTo(r.left()+i,r.top()); - lightgreyPath.lineTo(r.left()+i,r.bottom()); - painter.drawPath(lightgreyPath); - } - } - if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){ - for(i = 0; i < ((r.top() + r.bottom())>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) { - lightgreyPath.moveTo(r.left() + 40,zeroHeight + i); - lightgreyPath.lineTo(r.right(),zeroHeight + i); - painter.drawPath(lightgreyPath); - lightgreyPath.moveTo(r.left() + 40,zeroHeight - i); - lightgreyPath.lineTo(r.right(),zeroHeight - i); - painter.drawPath(lightgreyPath); - } - } - - int startMax = - (GraphTraceLen - (int)((r.right() - r.left() - 40) / GraphPixelsPerPoint)); - if(startMax < 0) { - startMax = 0; - } - if(GraphStart > startMax) { - GraphStart = startMax; - } - - int absYMax = 1; - - for(i = GraphStart; ; i++) { - if(i >= GraphTraceLen) { - break; - } - if(fabs((double)GraphBuffer[i]) > absYMax) { - absYMax = (int)fabs((double)GraphBuffer[i]); - } - int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); - if(x > r.right()) { - break; - } - } - - absYMax = (int)(absYMax*1.2 + 1); - - // number of points that will be plotted - int span = (int)((r.right() - r.left()) / GraphPixelsPerPoint); - // one label every 100 pixels, let us say - int labels = (r.right() - r.left() - 40) / 100; - if(labels <= 0) labels = 1; - int pointsPerLabel = span / labels; - if(pointsPerLabel <= 0) pointsPerLabel = 1; - - int yMin = INT_MAX; - int yMax = INT_MIN; - int yMean = 0; - int n = 0; - - for(i = GraphStart; ; i++) { - if(i >= GraphTraceLen) { - break; - } - int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); - if(x > r.right() + GraphPixelsPerPoint) { - break; - } - - int y = GraphBuffer[i]; - if(y < yMin) { - yMin = y; - } - if(y > yMax) { - yMax = y; - } - yMean += y; - n++; - - y = (y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight; - if(i == GraphStart) { - penPath.moveTo(x, y); - } else { - penPath.lineTo(x, y); - } - - if(GraphPixelsPerPoint > 10) { - QRect f(QPoint(x - 3, y - 3),QPoint(x + 3, y + 3)); - painter.fillRect(f, brush); - } - - if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) { - whitePath.moveTo(x, zeroHeight - 3); - whitePath.lineTo(x, zeroHeight + 3); - - char str[100]; - sprintf(str, "+%d", (i - GraphStart)); - - painter.setPen(QColor(255, 255, 255)); - QRect size; - QFontMetrics metrics(painter.font()); - size = metrics.boundingRect(str); - painter.drawText(x - (size.right() - size.left()), zeroHeight + 9, str); - - penPath.moveTo(x,y); - } - - if(i == CursorAPos || i == CursorBPos) { - QPainterPath *cursorPath; - - if(i == CursorAPos) { - cursorPath = &cursorAPath; - } else { - cursorPath = &cursorBPath; - } - cursorPath->moveTo(x, r.top()); - cursorPath->lineTo(x, r.bottom()); - penPath.moveTo(x, y); - } - } - - if(n != 0) { - yMean /= n; - } - - painter.setPen(QColor(255, 255, 255)); - painter.drawPath(whitePath); - painter.setPen(pen); - painter.drawPath(penPath); - painter.setPen(QColor(255, 255, 0)); - painter.drawPath(cursorAPath); - painter.setPen(QColor(255, 0, 255)); - painter.drawPath(cursorBPath); - - char str[100]; - sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]", - GraphStart, yMax, yMin, yMean, n, GraphTraceLen, - CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor,GraphPixelsPerPoint,CursorAPos,GraphBuffer[CursorAPos],CursorBPos,GraphBuffer[CursorBPos]); - - painter.setPen(QColor(255, 255, 255)); - painter.drawText(50, r.bottom() - 20, str); -} - -ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1) -{ - resize(600, 500); - - QPalette palette(QColor(0,0,0,0)); - palette.setColor(QPalette::WindowText, QColor(255,255,255)); - palette.setColor(QPalette::Text, QColor(255,255,255)); - palette.setColor(QPalette::Button, QColor(100, 100, 100)); - setPalette(palette); - setAutoFillBackground(true); -} - -void ProxWidget::closeEvent(QCloseEvent *event) -{ - event->ignore(); - this->hide(); -} - -void ProxWidget::mouseMoveEvent(QMouseEvent *event) -{ - int x = event->x(); - x -= 40; - x = (int)(x / GraphPixelsPerPoint); - x += GraphStart; - if((event->buttons() & Qt::LeftButton)) { - CursorAPos = x; - } else if (event->buttons() & Qt::RightButton) { - CursorBPos = x; - } - - - this->update(); -} - -void ProxWidget::keyPressEvent(QKeyEvent *event) -{ - switch(event->key()) { - case Qt::Key_Down: - if(GraphPixelsPerPoint <= 50) { - GraphPixelsPerPoint *= 2; - } - break; - - case Qt::Key_Up: - if(GraphPixelsPerPoint >= 0.02) { - GraphPixelsPerPoint /= 2; - } - break; - - case Qt::Key_Right: - if(GraphPixelsPerPoint < 20) { - GraphStart += (int)(20 / GraphPixelsPerPoint); - } else { - GraphStart++; - } - break; - - case Qt::Key_Left: - if(GraphPixelsPerPoint < 20) { - GraphStart -= (int)(20 / GraphPixelsPerPoint); - } else { - GraphStart--; - } - break; - - default: - QWidget::keyPressEvent(event); - return; - break; - } - - this->update(); -} diff --git a/linux/proxguiqt.h b/linux/proxguiqt.h deleted file mode 100644 index 58ff8326..00000000 --- a/linux/proxguiqt.h +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include - -class ProxWidget : public QWidget -{ - Q_OBJECT; - - private: - int GraphStart; - double GraphPixelsPerPoint; - int CursorAPos; - int CursorBPos; - - public: - ProxWidget(QWidget *parent = 0); - - protected: - void paintEvent(QPaintEvent *event); - void closeEvent(QCloseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); } - void keyPressEvent(QKeyEvent *event); -}; - -class ProxGuiQT : public QObject -{ - Q_OBJECT; - - private: - QApplication *plotapp; - ProxWidget *plotwidget; - int argc; - char **argv; - void (*main_func)(void); - - public: - ProxGuiQT(int argc, char **argv); - ~ProxGuiQT(void); - void ShowGraphWindow(void); - void RepaintGraphWindow(void); - void HideGraphWindow(void); - void MainLoop(void); - - private slots: - void _ShowGraphWindow(void); - void _RepaintGraphWindow(void); - void _HideGraphWindow(void); - - signals: - void ShowGraphWindowSignal(void); - void RepaintGraphWindowSignal(void); - void HideGraphWindowSignal(void); -}; diff --git a/linux/proxmark3.c b/linux/proxmark3.c deleted file mode 100644 index 2839db93..00000000 --- a/linux/proxmark3.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "translate.h" -#include "../winsrc/prox.h" -#include "proxmark3.h" -#include "proxgui.h" - -struct usb_receiver_arg { - int run; -}; - -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 (ReceiveCommandP(&cmdbuf) > 0) { - int i; - - for (i=0; iusb_present == 1) { - pthread_create(&reader_thread, NULL, &usb_receiver, &rarg); - } - cmd = readline(PROXPROMPT); - rarg.run=0; - if (arg->usb_present == 1) { - pthread_join(reader_thread, NULL); - } - - if (cmd) { - if (cmd[0] != 0x00) { - CommandReceived(cmd); - add_history(cmd); - } - free(cmd); - } else { - printf("\n"); - break; - } - } - - 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; -} diff --git a/linux/proxmark3.h b/linux/proxmark3.h deleted file mode 100644 index 67d80841..00000000 --- a/linux/proxmark3.h +++ /dev/null @@ -1,14 +0,0 @@ -#define PROXPROMPT "proxmark3> " - -#define FLASH_ADDR_OS 0x10000 -#define FLASH_ADDR_FPGA 0x2000 - -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); - -void setlogfilename(char *fn); diff --git a/linux/snooper.c b/linux/snooper.c deleted file mode 100644 index 63fa406f..00000000 --- a/linux/snooper.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "translate.h" -#include "../winsrc/prox.h" -#include "proxmark3.h" - -#define HANDLE_ERROR if (error_occured) { \ - 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++) { - ReceiveCommandP(&cmdbuf); - } - HANDLE_ERROR - - CommandReceived("hi14alist"); - HANDLE_ERROR - } - } - - CloseProxmark(); - return 0; -} diff --git a/linux/translate.h b/linux/translate.h deleted file mode 100644 index 145268a0..00000000 --- a/linux/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/linux/unbind-proxmark b/linux/unbind-proxmark deleted file mode 100755 index 986c0015..00000000 --- a/linux/unbind-proxmark +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -for i in /sys/bus/usb/devices/*; do - if grep "9ac4" "${i}/idVendor" >/dev/null 2>&1; then - echo "Found Proxmark..." - dev=`basename "${i}"` - - for j in /sys/bus/usb/drivers/usbhid/*; do - if basename "${j}"|grep "^${dev}" >/dev/null; then - bound="`basename "${j}"`" - echo "Unbinding ${bound}..." - echo -n "${bound}" >/sys/bus/usb/drivers/usbhid/unbind - fi - done - fi -done diff --git a/linux/usb.c b/linux/usb.c deleted file mode 100644 index 4f3b4e7e..00000000 --- a/linux/usb.c +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "translate.h" -#include "../winsrc/prox.h" -#include "proxmark3.h" - -usb_dev_handle *devh = NULL; -static unsigned int claimed_iface = 0; -unsigned char return_on_error = 0; -unsigned char error_occured = 0; - -void SendCommand(UsbCommand *c, BOOL wantAck) { - int ret; - -#if 0 - printf("Sending %d bytes\n", sizeof(UsbCommand)); -#endif - 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; - } - - if(wantAck) { - UsbCommand ack; - ReceiveCommand(&ack); - if(ack.cmd != CMD_ACK) { - printf("bad ACK\n"); - exit(-1); - } - } -} - -int ReceiveCommandP(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 0; - - 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 0; - } - } else { - if (ret && (ret < sizeof(UsbCommand))) { - fprintf(stderr, "Read only %d instead of requested %d bytes!\n", - ret, (int)sizeof(UsbCommand)); - } - -#if 0 - { - int i; - - printf("Read %d bytes\n", ret); - for (i = 0; i < ret; i++) { - printf("0x%02X ", ((unsigned char*)c)[i]); - if (!((i+1)%8)) - printf("\n"); - } - printf("\n"); - } -#endif - } - - return ret; -} - -void ReceiveCommand(UsbCommand *c) { - while(ReceiveCommandP(c)<0) {} -} - -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/linux/windows.h b/linux/windows.h deleted file mode 100644 index e69de29b..00000000 diff --git a/winsrc/Makefile b/winsrc/Makefile deleted file mode 100644 index 1c8287f8..00000000 --- a/winsrc/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -CC=cl -BASE_DIR ?= "..\..\devkitWIN" -BASE_DEFS = /D_WIN32_WINNT=0x501 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x600 /DWIN32_LEAN_AND_MEAN /DWIN32 /D_MT /D_CRT_SECURE_NO_WARNINGS -BASE_CFLAGS = /W3 /nologo /Zi /MT /Fdobj/vc90.pdb -LIB = $(BASE_DIR)\lib - -DEFINES = $(BASE_DEFS) -INCLUDES = /I$(BASE_DIR)\include -CFLAGS = $(BASE_CFLAGS) $(INCLUDES) - -OBJDIR = obj - -OBJS = $(OBJDIR)\prox.obj \ - $(OBJDIR)\gui.obj \ - $(OBJDIR)\command.obj - -LIBS = $(LIB)\user32.lib $(LIB)\gdi32.lib $(LIB)\setupapi.lib $(LIB)\libcmt.lib $(LIB)\oldnames.lib $(LIB)\kernel32.lib - -all: proxmark3 - -proxmark3: - $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/prox.obj prox.cpp - $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/gui.obj gui.cpp - $(CC) $(CFLAGS) $(DEFINES) -c -Foobj/command.obj command.cpp - $(CC) $(CFLAGS) $(DEFINES) -Fe$(OBJDIR)/prox.exe $(OBJS) $(LIBS) - copy obj\prox.exe . - -clean: - del /q obj\*.obj - del /q obj\*.ilk - del /q obj\*.exe - del /q obj\*.pdb - del prox.exe \ No newline at end of file diff --git a/winsrc/command.cpp b/winsrc/command.cpp deleted file mode 100644 index 0214a0ab..00000000 --- a/winsrc/command.cpp +++ /dev/null @@ -1,3093 +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 (##) -//----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include - -#include "prox.h" -#include "../common/iso14443_crc.c" -#include "../common/crc16.c" - -#define arraylen(x) (sizeof(x)/sizeof((x)[0])) -#define BIT(x) GraphBuffer[x * clock] -#define BITS (GraphTraceLen / clock) - -int go = 0; -static int CmdHisamplest(char *str, int nrlow); - -static void GetFromBigBuf(BYTE *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; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return; - } - - memcpy(dest+(i*4), c.d.asBytes, 48); - } -} - -static void CmdReset(char *str) -{ - UsbCommand c; - c.cmd = CMD_HARDWARE_RESET; - SendCommand(&c, FALSE); -} - -static void CmdBuffClear(char *str) -{ - UsbCommand c; - c.cmd = CMD_BUFF_CLEAR; - SendCommand(&c, FALSE); - CmdClearGraph(TRUE); -} - -static void CmdQuit(char *str) -{ - exit(0); -} - -static void CmdHIDdemodFSK(char *str) -{ - UsbCommand c; - c.cmd = CMD_HID_DEMOD_FSK; - SendCommand(&c, FALSE); -} - -static void CmdTune(char *str) -{ - UsbCommand c; - c.cmd = CMD_MEASURE_ANTENNA_TUNING; - SendCommand(&c, FALSE); -} - -static void CmdHi15read(char *str) -{ - UsbCommand c; - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693; - SendCommand(&c, FALSE); -} - -static void CmdHi14read(char *str) -{ - UsbCommand c; - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - - -/* 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; - c.cmd = CMD_READ_SRI512_TAG; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -/* 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; - c.cmd = CMD_READ_SRIX4K_TAG; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - - - -// ## New command -static void CmdHi14areader(char *str) -{ - UsbCommand c; - c.cmd = CMD_READER_ISO_14443a; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -// ## New command -static void CmdHi15reader(char *str) -{ - UsbCommand c; - c.cmd = CMD_READER_ISO_15693; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -// ## New command -static void CmdHi15tag(char *str) -{ - UsbCommand c; - c.cmd = CMD_SIMTAG_ISO_15693; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -static void CmdHi14read_sim(char *str) -{ - UsbCommand c; - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -static void CmdHi14readt(char *str) -{ - UsbCommand c; - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); - - //CmdHisamplest(str); - while(CmdHisamplest(str,atoi(str))==0) { - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); - } - RepaintGraphWindow(); -} - -static void CmdHisimlisten(char *str) -{ - UsbCommand c; - c.cmd = CMD_SIMULATE_TAG_HF_LISTEN; - SendCommand(&c, FALSE); -} - -static void CmdHi14sim(char *str) -{ - UsbCommand c; - c.cmd = CMD_SIMULATE_TAG_ISO_14443; - SendCommand(&c, FALSE); -} - -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; - UsbCommand c; - - while (sscanf(&str[i++], "%1x", &n ) == 1) { - hi=(hi<<4)|(lo>>28); - lo=(lo<<4)|(n&0xf); - } - - c.cmd = CMD_SIMULATE_TAG_ISO_14443a; - // c.ext should be set to *str or convert *str to the correct format for a uid - c.ext1 = hi; - c.ext2 = lo; - PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo); - SendCommand(&c, FALSE); -} - -static void CmdHi14snoop(char *str) -{ - UsbCommand c; - c.cmd = CMD_SNOOP_ISO_14443; - SendCommand(&c, FALSE); -} - -static void CmdHi14asnoop(char *str) -{ - UsbCommand c; - c.cmd = CMD_SNOOP_ISO_14443a; - SendCommand(&c, FALSE); -} - -static void CmdLegicRfSim(char *str) -{ - UsbCommand c; - c.cmd = CMD_SIMULATE_TAG_LEGIC_RF; - SendCommand(&c, FALSE); -} - -static void CmdLegicRfRead(char *str) -{ - UsbCommand c; - c.cmd = CMD_READER_LEGIC_RF; - SendCommand(&c, FALSE); -} - -static void CmdFPGAOff(char *str) // ## FPGA Control -{ - UsbCommand c; - c.cmd = CMD_FPGA_MAJOR_MODE_OFF; - SendCommand(&c, FALSE); -} - -/* 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]; - char *s = "0"; - - /* 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(s); - - /* booyah! */ - RepaintGraphWindow(); - - CmdLosim(s); -} - -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; - - /* convert to bitstream if necessary */ - ChkBitstream(str); - - for (i = 0; i < GraphTraceLen; i += 48) { - UsbCommand c; - int j; - for(j = 0; j < 48; j++) { - c.d.asBytes[j] = GraphBuffer[i+j]; - } - c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - } - - UsbCommand c; - c.cmd = CMD_SIMULATE_TAG_125K; - c.ext1 = GraphTraceLen; - SendCommand(&c, FALSE); -} - -static void CmdLosimBidir(char *str) -{ - UsbCommand c; - c.cmd = CMD_LF_SIMULATE_BIDIR; - c.ext1 = 47; /* Set ADC to twice the carrier for a slight supersampling */ - c.ext2 = 384; - SendCommand(&c, FALSE); -} - -static void CmdLoread(char *str) -{ - UsbCommand c; - // 'h' means higher-low-frequency, 134 kHz - if(*str == 'h') { - c.ext1 = 1; - } else if (*str == '\0') { - c.ext1 = 0; - } else { - PrintToScrollback("use 'loread' or 'loread h'"); - return; - } - c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K; - SendCommand(&c, FALSE); -} - -static void CmdDetectReader(char *str) -{ - UsbCommand c; - // 'l' means LF - 125/134 kHz - if(*str == 'l') { - c.ext1 = 1; - } else if (*str == 'h') { - c.ext1 = 2; - } else if (*str != '\0') { - PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'"); - return; - } - c.cmd = CMD_LISTEN_READER_FIELD; - SendCommand(&c, FALSE); -} - -/* send a command before reading */ -static void CmdLoCommandRead(char *str) -{ - static char dummy[3]; - - dummy[0]= ' '; - - UsbCommand c; - c.cmd = CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K; - sscanf(str, "%i %i %i %s %s", &c.ext1, &c.ext2, &c.ext3, (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, FALSE); -} - -static void CmdLosamples(char *str) -{ - int cnt = 0; - int i; - int n; - - n=atoi(str); - if (n==0) n=128; - if (n>16000) n=16000; - - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - if (!go) - PrintToScrollback("bad resp"); - return; - } - int j; - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128; - } - } - GraphTraceLen = n*4; - RepaintGraphWindow(); -} - -static void CmdBitsamples(char *str) -{ - int cnt = 0; - int i; - int n; - - n = 3072; - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return; - } - int j, k; - for(j = 0; j < 48; j++) { - for(k = 0; k < 8; k++) { - if(c.d.asBytes[j] & (1 << (7 - k))) { - GraphBuffer[cnt++] = 1; - } else { - GraphBuffer[cnt++] = 0; - } - } - } - } - GraphTraceLen = cnt; - RepaintGraphWindow(); -} - -static void CmdHisamples(char *str) -{ - int cnt = 0; - int i; - int n; - n = 1000; - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return; - } - int j; - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]); - } - } - GraphTraceLen = n*4; - - RepaintGraphWindow(); -} - -static int CmdHisamplest(char *str, int nrlow) -{ - int cnt = 0; - int t1, t2; - int i; - int n; - int hasbeennull; - int show; - - - n = 1000; - hasbeennull = 0; - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return 0; - } - int j; - for(j = 0; j < 48; j++) { - t2 = (int)((BYTE)c.d.asBytes[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; - int n; - int requested = atoi(str); - int delivered = 0; - - if(atoi(str) == 0) { - n = 12; - requested = 12; - } else { - n = atoi(str)/4; - } - - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return; - } - int j; - for(j = 0; j < 48; j += 8) { - PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x", - c.d.asBytes[j+0], - c.d.asBytes[j+1], - c.d.asBytes[j+2], - c.d.asBytes[j+3], - c.d.asBytes[j+4], - c.d.asBytes[j+5], - c.d.asBytes[j+6], - c.d.asBytes[j+7], - c.d.asBytes[j+8] - ); - delivered += 8; - if(delivered >= requested) - break; - } - if(delivered >= requested) - break; - } -} - -static void CmdHisampless(char *str) -{ - int cnt = 0; - int i; - int n; - - if(atoi(str) == 0) { - n = 1000; - } else { - n = atoi(str)/4; - } - - for(i = 0; i < n; i += 12) { - UsbCommand c; - c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K; - c.ext1 = i; - SendCommand(&c, FALSE); - ReceiveCommand(&c); - if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) { - PrintToScrollback("bad resp"); - return; - } - int j; - for(j = 0; j < 48; j++) { - GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]); - } - } - GraphTraceLen = cnt; - - RepaintGraphWindow(); -} - -static WORD Iso15693Crc(BYTE *v, int n) -{ - DWORD reg; - int i, j; - - reg = 0xffff; - for(i = 0; i < n; i++) { - reg = reg ^ ((DWORD)v[i]); - for (j = 0; j < 8; j++) { - if (reg & 0x0001) { - reg = (reg >> 1) ^ 0x8408; - } else { - reg = (reg >> 1); - } - } - } - - return (WORD)~reg; -} - -static void CmdHi14bdemod(char *str) -{ - int i, j, iold; - int isum, qsum; - int outOfWeakAt; - BOOL negateI, negateQ; - - BYTE 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; - - WORD 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; - } - } - - BYTE 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) -{ - BYTE 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 = *((DWORD *)(got+i)); - if(timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - int metric = *((DWORD *)(got+i+4)); - - int len = got[i+8]; - - if(len > 100) { - break; - } - if(i + len >= 900) { - break; - } - - BYTE *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) { - BYTE 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) -{ - BYTE 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 = *((DWORD *)(got+i)); - if(timestamp & 0x80000000) { - timestamp &= 0x7fffffff; - isResponse = 1; - } else { - isResponse = 0; - } - - int metric = 0; - int parityBits = *((DWORD *)(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; - } - - BYTE *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) { - BYTE 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; - BYTE outBuf[20]; - memset(outBuf, 0, sizeof(outBuf)); - BYTE 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; - DWORD 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); - - BYTE 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; - c.cmd = CMD_READ_TI_TYPE; - SendCommand(&c, FALSE); -} - -// write new data to a r/w TI tag -static void CmdTIWrite(char *str) -{ - UsbCommand c; - int res=0; - - c.cmd = CMD_WRITE_TI_TYPE; - res = sscanf(str, "0x%x 0x%x 0x%x ", &c.ext1, &c.ext2, &c.ext3); - if (res == 2) c.ext3=0; - if (res<2) - PrintToScrollback("Please specify the data as two hex strings, optionally the CRC as a third"); - else - SendCommand(&c, FALSE); -} - -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; - WORD 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); - - BYTE bits[1+64+16+8+16]; - bits[sizeof(bits)-1] = '\0'; - - DWORD 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 - BYTE 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 - BYTE 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; - - BYTE 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; - UsbCommand c; - - 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); - - c.cmd = CMD_HID_SIM_TAG; - c.ext1 = hi; - c.ext2 = lo; - SendCommand(&c, FALSE); -} - -static void CmdReadmem(char *str) -{ - UsbCommand c; - c.cmd = CMD_READ_MEM; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -static void CmdVersion(char *str) -{ - UsbCommand c; - c.cmd = CMD_VERSION; - SendCommand(&c, FALSE); -} - -static void CmdLcdReset(char *str) -{ - UsbCommand c; - c.cmd = CMD_LCD_RESET; - c.ext1 = atoi(str); - SendCommand(&c, FALSE); -} - -static void CmdLcd(char *str) -{ - int i, j; - UsbCommand c; - c.cmd = CMD_LCD; - sscanf(str, "%x %d", &i, &j); - while (j--) { - c.ext1 = i&0x1ff; - SendCommand(&c, FALSE); - } -} - -/* - * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below - * 600kHz. - */ -static void CmdSetDivisor(char *str) -{ - UsbCommand c; - c.cmd = CMD_SET_LF_DIVISOR; - c.ext1 = atoi(str); - if (( c.ext1<0) || (c.ext1>255)) { - PrintToScrollback("divisor must be between 19 and 255"); - } else { - SendCommand(&c, FALSE); - PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1)); - } -} - -static void CmdSetMux(char *str) -{ - UsbCommand c; - c.cmd = CMD_SET_ADC_MUX; - if(strcmp(str, "lopkd") == 0) { - c.ext1 = 0; - } else if(strcmp(str, "loraw") == 0) { - c.ext1 = 1; - } else if(strcmp(str, "hipkd") == 0) { - c.ext1 = 2; - } else if(strcmp(str, "hiraw") == 0) { - c.ext1 = 3; - } - SendCommand(&c, FALSE); -} - -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[] = { - {"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"}, - {"detectreader", CmdDetectReader, 0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - {"em410xsim", CmdEM410xsim, 1, " -- Simulate EM410x tag"}, - {"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"}, - {"exit", CmdQuit, 1, "Exit program"}, - {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"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"}, - {"hi14alist", CmdHi14alist, 0, "List ISO 14443a history"}, - {"hi14areader", CmdHi14areader, 0, "Act like an ISO14443 Type A reader"}, - {"hi14asim", CmdHi14asim, 0, " -- Fake ISO 14443a tag"}, - {"hi14asnoop", CmdHi14asnoop, 0, "Eavesdrop ISO 14443 Type A"}, - {"hi14bdemod", CmdHi14bdemod, 1, "Demodulate ISO14443 Type B from tag"}, - {"hi14list", CmdHi14list, 0, "List ISO 14443 history"}, - {"hi14read", CmdHi14read, 0, "Read HF tag (ISO 14443)"}, - {"hi14sim", CmdHi14sim, 0, "Fake ISO 14443 tag"}, - {"hi14snoop", CmdHi14snoop, 0, "Eavesdrop ISO 14443"}, - {"hi15demod", CmdHi15demod, 1, "Demodulate ISO15693 from tag"}, - {"hi15read", CmdHi15read, 0, "Read HF tag (ISO 15693)"}, - {"hi15reader", CmdHi15reader, 0, "Act like an ISO15693 reader"}, - {"hi15sim", CmdHi15tag, 0, "Fake an ISO15693 tag"}, - {"hiddemod", CmdHiddemod, 1, "Demodulate HID Prox Card II (not optimal)"}, - {"hide", CmdHide, 1, "Hide graph window"}, - {"hidfskdemod", CmdHIDdemodFSK, 0, "Realtime HID FSK demodulator"}, - {"hidsimtag", CmdHIDsimTAG, 0, " -- HID tag simulator"}, - {"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"}, - {"hisimlisten", CmdHisimlisten, 0, "Get HF samples as fake tag"}, - {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, - {"indalademod", CmdIndalademod, 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, - {"lcd", CmdLcd, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLcdReset, 0, "Hardware reset LCD"}, - {"legicrfsim", CmdLegicRfSim, 0, "Start the LEGIC RF tag simulator"}, - {"legicrfread", CmdLegicRfRead, 0, "Start the LEGIC RF reader"}, - {"load", CmdLoad, 1, " -- Load trace (to graph window"}, - {"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)"}, - {"losamples", CmdLosamples, 0, "[128 - 16000] -- Get raw samples for LF tag"}, - {"losim", CmdLosim, 0, "Simulate LF tag"}, - {"losimbidir", CmdLosimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, - {"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"}, - {"quit", CmdQuit, 1, "Quit program"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"save", CmdSave, 1, " -- Save trace (from graph window)"}, - {"scale", CmdScale, 1, " -- Set cursor display scale"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"sri512read", CmdSri512read, 0, " -- Read contents of a SRI512 tag"}, - {"srix4kread", CmdSrix4kread, 0, " -- Read contents of a SRIX4K tag"}, - {"tidemod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF 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"}, - {"threshold", CmdThreshold, 1, "Maximize/minimize every value in the graph window depending on threshold"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"vchdemod", CmdVchdemod, 0, "['clone'] -- Demodulate samples for VeriChip"}, - {"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"}, - {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, -}; - -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[256]; - - 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) -{ - switch(c->cmd) { - case CMD_DEBUG_PRINT_STRING: { - char s[100]; - if(c->ext1 > 70 || c->ext1 < 0) { - c->ext1 = 0; - } - memcpy(s, c->d.asBytes, c->ext1); - s[c->ext1] = '\0'; - PrintToScrollback("#db# %s", s); - break; - } - - case CMD_DEBUG_PRINT_INTEGERS: - PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3); - break; - - case CMD_MEASURED_ANTENNA_TUNING: { - int peakv, peakf; - int vLf125, vLf134, vHf; - vLf125 = c->ext1 & 0xffff; - vLf134 = c->ext1 >> 16; - vHf = c->ext2 & 0xffff;; - peakf = c->ext3 & 0xffff; - peakv = c->ext3 >> 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."); - break; - } - default: - PrintToScrollback("unrecognized command %08x\n", c->cmd); - break; - } -} diff --git a/winsrc/gui.cpp b/winsrc/gui.cpp deleted file mode 100644 index 3753a86e..00000000 --- a/winsrc/gui.cpp +++ /dev/null @@ -1,533 +0,0 @@ -//----------------------------------------------------------------------------- -// Routines for the user interface when doing interactive things with prox -// cards; this is basically a command line thing, in one window, and then -// another window to do the graphs. -// Jonathan Westhues, Sept 2005 -//----------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include - -#include "prox.h" - -#define oops() do { \ - char line[100]; \ - sprintf(line, "Internal error at line %d file '%s'", __LINE__, \ - __FILE__); \ - MessageBox(NULL, line, "Error", MB_ICONERROR); \ - exit(-1); \ -} while(0) - -void dbp(char *str, ...) -{ - va_list f; - char buf[1024]; - va_start(f, str); - vsprintf(buf, str, f); - OutputDebugString(buf); - OutputDebugString("\n"); -} - -int GraphBuffer[MAX_GRAPH_TRACE_LEN]; -int GraphTraceLen; -int PlotGridX, PlotGridY; - -HPEN GreyPenLite, GreyPen, GreenPen, WhitePen, YellowPen; -HBRUSH GreenBrush, YellowBrush; - -static int GraphStart = 0; -static double GraphPixelsPerPoint = 1; - -static int CursorAPos; -static int CursorBPos; -double CursorScaleFactor = 1.0; -static HPEN CursorAPen; -static HPEN CursorBPen; - -static HWND CommandWindow; -static HWND GraphWindow; -static HWND ScrollbackEdit; -static HWND CommandEdit; - -#define COMMAND_HISTORY_MAX 16 -static char CommandHistory[COMMAND_HISTORY_MAX][256]; -static int CommandHistoryPos = -1; -static int CommandHistoryNext; - -static HFONT MyFixedFont; -#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE) - -void ExecCmd(char *cmd) -{ -} - -int CommandFinished; -int offset = 64; - -static void ResizeCommandWindow(void) -{ - int w, h; - RECT r; - GetClientRect(CommandWindow, &r); - w = r.right - r.left; - h = r.bottom - r.top; - MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE); - MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE); -} - -void RepaintGraphWindow(void) -{ - InvalidateRect(GraphWindow, NULL, TRUE); -} - -static LRESULT CALLBACK - CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_DESTROY: - case WM_QUIT: - exit(0); - return 0; - - case WM_SIZE: - ResizeCommandWindow(); - return 0; - - case WM_SETFOCUS: - SetFocus(CommandEdit); - break; - - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - - return 1; -} - -static void PaintGraph(HDC hdc) -{ - RECT r; - HBRUSH brush; - HPEN pen; - char str[250]; - int yMin = INT_MAX; - int yMax = INT_MIN; - int yMean = 0; - int startMax = 0; - int absYMax = 1; - int n = 0, i = 0; - - brush = GreenBrush; - pen = GreenPen; - - GetClientRect(GraphWindow, &r); - int zeroHeight = (r.top + r.bottom) >> 1; - - // plot X and Y grid lines - if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) { - for(i = offset; i < r.right; i += (int)(PlotGridX * GraphPixelsPerPoint)) { - SelectObject(hdc, GreyPenLite); - MoveToEx(hdc, r.left + i, r.top, NULL); - LineTo(hdc, r.left + i, r.bottom); - } - } - - if ((PlotGridY > 0) && ((PlotGridY * GraphPixelsPerPoint) > 1)){ - for(i = 0; i < ((r.top + r.bottom)>>1); i += (int)(PlotGridY * GraphPixelsPerPoint)) { - SelectObject(hdc, GreyPenLite); - MoveToEx(hdc, r.left, zeroHeight + i, NULL); - LineTo(hdc, r.right, zeroHeight + i); - MoveToEx(hdc, r.left, zeroHeight - i, NULL); - LineTo(hdc, r.right, zeroHeight - i); - } - } - - // print vertical separator white line on the left of the window - SelectObject(hdc, WhitePen); - MoveToEx(hdc, r.left + offset, r.top, NULL); - LineTo(hdc, r.left + offset, r.bottom); - - // print horizontal grey zero axis line - SelectObject(hdc, GreyPen); - MoveToEx(hdc, r.left, zeroHeight, NULL); - LineTo(hdc, r.right, zeroHeight); - - startMax = (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint)); - // check boundaries - if(startMax < 0) startMax = 0; - if(GraphStart > startMax) GraphStart = startMax; - if(GraphStart < 0) GraphStart = 0; - - - SelectObject(hdc, pen); - - // go over the portion of the graph to be displayed and find the largest - // absolute value which will be used to auto scale the graph when displayed - for(i = GraphStart; ; i++) { - if(i >= GraphTraceLen) { - break; - } - if(fabs((double)GraphBuffer[i]) > absYMax) { - absYMax = (int)fabs((double)GraphBuffer[i]); - } - int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint); - if(x > r.right) { - break; - } - } - - absYMax = (int)(absYMax*1.2 + 1); - SelectObject(hdc, MyFixedFont); - SetTextColor(hdc, RGB(255, 255, 255)); - SetBkColor(hdc, RGB(0, 0, 0)); - - // number of points that will be plotted - double span = (int)((r.right - r.left) / GraphPixelsPerPoint); - - // one label every offset pixels, let us say - int labels = (r.right - r.left - offset) / offset; - if(labels <= 0) labels = 1; - // round to nearest power of 2 - int pointsPerLabel = (int)(log(span / labels)/log(2.0)); - if(pointsPerLabel <= 0) pointsPerLabel = 1; - pointsPerLabel = (int)pow(2.0,pointsPerLabel); - - // go over the graph and plot samples and labels - for(i = GraphStart; ; i++) { - if(i >= GraphTraceLen) { - break; - } - int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint); - if(x > r.right + GraphPixelsPerPoint) { - break; - } - - int y = GraphBuffer[i]; - if(y < yMin) yMin = y; - if(y > yMax) yMax = y; - yMean += y; - n++; - - y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight; - if(i == GraphStart) { - MoveToEx(hdc, x, y, NULL); - } else { - LineTo(hdc, x, y); - } - - if(GraphPixelsPerPoint > 10) { - RECT f; - f.left = x - 3; - f.top = y - 3; - f.right = x + 3; - f.bottom = y + 3; - FillRect(hdc, &f, brush); - } - - // plot labels - if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) { - SelectObject(hdc, WhitePen); - MoveToEx(hdc, x, zeroHeight - 8, NULL); - LineTo(hdc, x, zeroHeight + 8); - - sprintf(str, "+%d", i); - SIZE size; - GetTextExtentPoint32(hdc, str, strlen(str), &size); - TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str)); - - SelectObject(hdc, pen); - MoveToEx(hdc, x, y, NULL); - } - - // plot measurement cursors - if(i == CursorAPos || i == CursorBPos) { - if(i == CursorAPos) { - SelectObject(hdc, CursorAPen); - } else { - SelectObject(hdc, CursorBPen); - } - MoveToEx(hdc, x, r.top, NULL); - LineTo(hdc, x, r.bottom); - - SelectObject(hdc, pen); - MoveToEx(hdc, x, y, NULL); - } - } - - if(n != 0) { - yMean /= n; - } - - // print misc information at bottom of graph window - sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f CursorA=%d [%d] CursorB=%d [%d]", - GraphStart, yMax, yMin, yMean, n, GraphTraceLen, - CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint, - CursorAPos, GraphBuffer[CursorAPos], CursorBPos, GraphBuffer[CursorBPos]); - TextOut(hdc, 50, r.bottom - 20, str, strlen(str)); -} - -static LRESULT CALLBACK - GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_DESTROY: - case WM_QUIT: - GraphWindow = NULL; - return DefWindowProc(hwnd, msg, wParam, lParam); - - case WM_SIZE: - RepaintGraphWindow(); - return 0; - - case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - if(GraphStart < 0) { - GraphStart = 0; - } - // This draws the trace. - PaintGraph(hdc); - EndPaint(hwnd, &ps); - break; - } - case WM_KEYDOWN: - switch(wParam) { - case VK_DOWN: - if(GraphPixelsPerPoint <= 8) { - GraphPixelsPerPoint *= 2; - } - break; - - case VK_UP: - if(GraphPixelsPerPoint >= 0.01) { - GraphPixelsPerPoint /= 2; - } - break; - - case VK_RIGHT: - if(GraphPixelsPerPoint < 16) { - GraphStart += (int)(16 / GraphPixelsPerPoint); - } else { - GraphStart++; - } - break; - - case VK_LEFT: - if(GraphPixelsPerPoint < 16) { - GraphStart -= (int)(16 / GraphPixelsPerPoint); - } else { - GraphStart--; - } - break; - - default: - goto nopaint; - } - RepaintGraphWindow(); -nopaint: - break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: { - int x = LOWORD(lParam); - x -= offset; - x = (int)(x / GraphPixelsPerPoint); - x += GraphStart; - - if(msg == WM_LBUTTONDOWN) { - CursorAPos = x; - } else { - CursorBPos = x; - } - RepaintGraphWindow(); - break; - } - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - - return 1; -} - -void PrintToScrollback(char *fmt, ...) -{ - va_list f; - char str[1024]; - strcpy(str, "\r\n"); - va_start(f, fmt); - vsprintf(str+2, fmt, f); - - static char TextBuf[1024*32]; - SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf), - (LPARAM)TextBuf); - - if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) { - strcat(TextBuf, str); - } else { - lstrcpyn(TextBuf, str, sizeof(TextBuf)); - } - - SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf); - SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX); -} - -void ShowGraphWindow(void) -{ - if(GraphWindow) return; - - GraphWindow = CreateWindowEx(0, "Graph", "graphed", - WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | - WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL, - NULL); - if(!GraphWindow) oops(); -} - -void HideGraphWindow(void) -{ - if(GraphWindow) { - DestroyWindow(GraphWindow); - GraphWindow = NULL; - } -} - -static void SetCommandEditTo(char *str) -{ - SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str); - SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str)); -} - -void ShowGui() -{ - WNDCLASSEX wc; - memset(&wc, 0, sizeof(wc)); - wc.cbSize = sizeof(wc); - - wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)CommandWindowProc; - wc.hInstance = NULL; - wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW); - wc.lpszClassName = "Command"; - wc.lpszMenuName = NULL; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - - if(!RegisterClassEx(&wc)) oops(); - - wc.lpszClassName = "Graph"; - wc.lpfnWndProc = (WNDPROC)GraphWindowProc; - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - - if(!RegisterClassEx(&wc)) oops(); - - CommandWindow = CreateWindowEx(0, "Command", "prox", - WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU | - WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL, - NULL); - if(!CommandWindow) oops(); - - ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "", - WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE | - ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL, - NULL, NULL); - - CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "", - WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE | - ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL); - - MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE, - ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - FF_DONTCARE, "Lucida Console"); - if(!MyFixedFont) - MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT); - - FixedFont(ScrollbackEdit); - FixedFont(CommandEdit); - - ResizeCommandWindow(); - SetFocus(CommandEdit); - - PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__); - PrintToScrollback(">> Connected to device"); - - GreyPenLite = CreatePen(PS_SOLID, 1, RGB(50, 50, 50)); - GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100)); - GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100)); - YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0)); - GreenBrush = CreateSolidBrush(RGB(100, 255, 100)); - YellowBrush = CreateSolidBrush(RGB(255, 255, 0)); - WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); - - CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0)); - CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255)); - - MSG msg; - for(;;) { - if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) { - char got[1024]; - SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got), - (LPARAM)got); - - if(strcmp(got, "cls")==0) { - SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)""); - } else { - CommandReceived(got); - } - SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)""); - - // Insert it into the command history, unless it is - // identical to the previous command in the history. - int prev = CommandHistoryNext - 1; - if(prev < 0) prev += COMMAND_HISTORY_MAX; - if(strcmp(CommandHistory[prev], got) != 0) { - strcpy(CommandHistory[CommandHistoryNext], got); - CommandHistoryNext++; - if(CommandHistoryNext == COMMAND_HISTORY_MAX) { - CommandHistoryNext = 0; - } - } - CommandHistoryPos = -1; - } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP && - msg.hwnd == CommandEdit) - { - if(CommandHistoryPos == -1) { - CommandHistoryPos = CommandHistoryNext; - } - CommandHistoryPos--; - if(CommandHistoryPos < 0) { - CommandHistoryPos = COMMAND_HISTORY_MAX-1; - } - SetCommandEditTo(CommandHistory[CommandHistoryPos]); - } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN && - msg.hwnd == CommandEdit) - { - CommandHistoryPos++; - if(CommandHistoryPos >= COMMAND_HISTORY_MAX) { - CommandHistoryPos = 0; - } - SetCommandEditTo(CommandHistory[CommandHistoryPos]); - } else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE && - msg.hwnd == CommandEdit) - { - SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)""); - } else { - if(msg.message == WM_KEYDOWN) { - CommandHistoryPos = -1; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - if (!offline) - { - UsbCommand c; - if(ReceiveCommandPoll(&c)) - UsbCommandReceived(&c); - } - - Sleep(10); - } -} diff --git a/winsrc/include/hidpi.h b/winsrc/include/hidpi.h deleted file mode 100644 index e9816cf4..00000000 --- a/winsrc/include/hidpi.h +++ /dev/null @@ -1,1787 +0,0 @@ -/*++ - -Copyright (c) 1996-1998 Microsoft Corporation - -Module Name: - - HIDPI.H - -Abstract: - - Public Interface to the HID parsing library. - -Environment: - - Kernel & user mode - ---*/ - -#ifndef __HIDPI_H__ -#define __HIDPI_H__ - -#include - -// Please include "hidsdi.h" to use the user space (dll / parser) -// Please include "hidpddi.h" to use the kernel space parser - -// -// Special Link collection values for using the query functions -// -// Root collection references the collection at the base of the link -// collection tree. -// Unspecifies, references all collections in the link collection tree. -// -#define HIDP_LINK_COLLECTION_ROOT ((USHORT) -1) -#define HIDP_LINK_COLLECTION_UNSPECIFIED ((USHORT) 0) - - -typedef enum _HIDP_REPORT_TYPE -{ - HidP_Input, - HidP_Output, - HidP_Feature -} HIDP_REPORT_TYPE; - -typedef struct _USAGE_AND_PAGE -{ - USAGE Usage; - USAGE UsagePage; -} USAGE_AND_PAGE, *PUSAGE_AND_PAGE; - -#define HidP_IsSameUsageAndPage(u1, u2) ((* (PULONG) &u1) == (* (PULONG) &u2)) - -typedef struct _HIDP_BUTTON_CAPS -{ - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - - USHORT BitField; - USHORT LinkCollection; // A unique internal index pointer - - USAGE LinkUsage; - USAGE LinkUsagePage; - - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - - ULONG Reserved[10]; - union { - struct { - USAGE UsageMin, UsageMax; - USHORT StringMin, StringMax; - USHORT DesignatorMin, DesignatorMax; - USHORT DataIndexMin, DataIndexMax; - } Range; - struct { - USAGE Usage, Reserved1; - USHORT StringIndex, Reserved2; - USHORT DesignatorIndex, Reserved3; - USHORT DataIndex, Reserved4; - } NotRange; - }; - -} HIDP_BUTTON_CAPS, *PHIDP_BUTTON_CAPS; - - -typedef struct _HIDP_VALUE_CAPS -{ - USAGE UsagePage; - UCHAR ReportID; - BOOLEAN IsAlias; - - USHORT BitField; - USHORT LinkCollection; // A unique internal index pointer - - USAGE LinkUsage; - USAGE LinkUsagePage; - - BOOLEAN IsRange; - BOOLEAN IsStringRange; - BOOLEAN IsDesignatorRange; - BOOLEAN IsAbsolute; - - BOOLEAN HasNull; // Does this channel have a null report union - UCHAR Reserved; - USHORT BitSize; // How many bits are devoted to this value? - - USHORT ReportCount; // See Note below. Usually set to 1. - USHORT Reserved2[5]; - - ULONG UnitsExp; - ULONG Units; - - LONG LogicalMin, LogicalMax; - LONG PhysicalMin, PhysicalMax; - - union { - struct { - USAGE UsageMin, UsageMax; - USHORT StringMin, StringMax; - USHORT DesignatorMin, DesignatorMax; - USHORT DataIndexMin, DataIndexMax; - } Range; - - struct { - USAGE Usage, Reserved1; - USHORT StringIndex, Reserved2; - USHORT DesignatorIndex, Reserved3; - USHORT DataIndex, Reserved4; - } NotRange; - }; -} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS; - -// -// Notes: -// -// ReportCount: When a report descriptor declares an Input, Output, or -// Feature main item with fewer usage declarations than the report count, then -// the last usage applies to all remaining unspecified count in that main item. -// (As an example you might have data that required many fields to describe, -// possibly buffered bytes.) In this case, only one value cap structure is -// allocated for these associtated fields, all with the same usage, and Report -// Count reflects the number of fields involved. Normally ReportCount is 1. -// To access all of the fields in such a value structure would require using -// HidP_GetUsageValueArray and HidP_SetUsageValueArray. HidP_GetUsageValue/ -// HidP_SetScaledUsageValue will also work, however, these functions will only -// work with the first field of the structure. -// - -// -// The link collection tree consists of an array of LINK_COLLECTION_NODES -// where the index into this array is the same as the collection number. -// -// Given a collection A which contains a subcollection B, A is defined to be -// the parent B, and B is defined to be the child. -// -// Given collections A, B, and C where B and C are children of A, and B was -// encountered before C in the report descriptor, B is defined as a sibling of -// C. (This implies, of course, that if B is a sibling of C, then C is NOT a -// sibling of B). -// -// B is defined as the NextSibling of C if and only if there exists NO -// child collection of A, call it D, such that B is a sibling of D and D -// is a sibling of C. -// -// E is defined to be the FirstChild of A if and only if for all children of A, -// F, that are not equivalent to E, F is a sibling of E. -// (This implies, of course, that the does not exist a child of A, call it G, -// where E is a sibling of G). In other words the first sibling is the last -// link collection found in the list. -// -// In other words, if a collection B is defined within the definition of another -// collection A, B becomes a child of A. All collections with the same parent -// are considered siblings. The FirstChild of the parent collection, A, will be -// last collection defined that has A as a parent. The order of sibling pointers -// is similarly determined. When a collection B is defined, it becomes the -// FirstChild of it's parent collection. The previously defined FirstChild of the -// parent collection becomes the NextSibling of the new collection. As new -// collections with the same parent are discovered, the chain of sibling is built. -// -// With that in mind, the following describes conclusively a data structure -// that provides direct traversal up, down, and accross the link collection -// tree. -// -// -typedef struct _HIDP_LINK_COLLECTION_NODE -{ - USAGE LinkUsage; - USAGE LinkUsagePage; - USHORT Parent; - USHORT NumberOfChildren; - USHORT NextSibling; - USHORT FirstChild; - ULONG CollectionType: 8; // As defined in 6.2.2.6 of HID spec - ULONG IsAlias : 1; // This link node is an allias of the next link node. - ULONG Reserved: 23; - PVOID UserContext; // The user can hang his coat here. -} HIDP_LINK_COLLECTION_NODE, *PHIDP_LINK_COLLECTION_NODE; - -// -// When a link collection is described by a delimiter, alias link collection -// nodes are created. (One for each usage within the delimiter). -// The parser assigns each capability description listed above only one -// link collection. -// -// If a control is defined within a collection defined by -// delimited usages, then that control is said to be within multiple link -// collections, one for each usage within the open and close delimiter tokens. -// Such multiple link collecions are said to be aliases. The first N-1 such -// collections, listed in the link collection node array, have their IsAlias -// bit set. The last such link collection is the link collection index used -// in the capabilities described above. -// Clients wishing to set a control in an aliased collection, should walk the -// collection array once for each time they see the IsAlias flag set, and use -// the last link collection as the index for the below accessor functions. -// -// NB: if IsAlias is set, then NextSibling should be one more than the current -// link collection node index. -// - -typedef PUCHAR PHIDP_REPORT_DESCRIPTOR; -typedef struct _HIDP_PREPARSED_DATA * PHIDP_PREPARSED_DATA; - -typedef struct _HIDP_CAPS -{ - USAGE Usage; - USAGE UsagePage; - USHORT InputReportByteLength; - USHORT OutputReportByteLength; - USHORT FeatureReportByteLength; - USHORT Reserved[17]; - - USHORT NumberLinkCollectionNodes; - - USHORT NumberInputButtonCaps; - USHORT NumberInputValueCaps; - USHORT NumberInputDataIndices; - - USHORT NumberOutputButtonCaps; - USHORT NumberOutputValueCaps; - USHORT NumberOutputDataIndices; - - USHORT NumberFeatureButtonCaps; - USHORT NumberFeatureValueCaps; - USHORT NumberFeatureDataIndices; -} HIDP_CAPS, *PHIDP_CAPS; - -typedef struct _HIDP_DATA -{ - USHORT DataIndex; - USHORT Reserved; - union { - ULONG RawValue; // for values - BOOLEAN On; // for buttons MUST BE TRUE for buttons. - }; -} HIDP_DATA, *PHIDP_DATA; -// -// The HIDP_DATA structure is used with HidP_GetData and HidP_SetData -// functions. -// -// The parser contiguously assigns every control (button or value) in a hid -// device a unique data index from zero to NumberXXXDataIndices -1 , inclusive. -// This value is found in the HIDP_BUTTON_CAPS and HIDP_VALUE_CAPS structures. -// -// Most clients will find the Get/Set Buttons / Value accessor functions -// sufficient to their needs, as they will allow the clients to access the -// data known to them while ignoring the other controls. -// -// More complex clients, which actually read the Button / Value Caps, and which -// do a value add service to these routines (EG Direct Input), will need to -// access all the data in the device without interest in the individual usage -// or link collection location. These are the clients that will find -// HidP_Data useful. -// - -typedef struct _HIDP_UNKNOWN_TOKEN -{ - UCHAR Token; - UCHAR Reserved[3]; - ULONG BitField; -} HIDP_UNKNOWN_TOKEN, *PHIDP_UNKNOWN_TOKEN; - -typedef struct _HIDP_EXTENDED_ATTRIBUTES -{ - UCHAR NumGlobalUnknowns; - UCHAR Reserved [3]; - PHIDP_UNKNOWN_TOKEN GlobalUnknowns; - // ... Additional attributes - ULONG Data [1]; // variableLength DO NOT ACCESS THIS FIELD -} HIDP_EXTENDED_ATTRIBUTES, *PHIDP_EXTENDED_ATTRIBUTES; - -NTSTATUS __stdcall -HidP_GetCaps ( - IN PHIDP_PREPARSED_DATA PreparsedData, - OUT PHIDP_CAPS Capabilities - ); -/*++ -Routine Description: - Returns a list of capabilities of a given hid device as described by its - preparsed data. - -Arguments: - PreparsedData The preparsed data returned from HIDCLASS. - Capabilities a HIDP_CAPS structure - -Return Value: -· HIDP_STATUS_SUCCESS -· HIDP_STATUS_INVALID_PREPARSED_DATA ---*/ - -NTSTATUS __stdcall -HidP_GetLinkCollectionNodes ( - OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, - IN OUT PULONG LinkCollectionNodesLength, - IN PHIDP_PREPARSED_DATA PreparsedData - ); -/*++ -Routine Description: - Return a list of PHIDP_LINK_COLLECTION_NODEs used to describe the link - collection tree of this hid device. See the above description of - struct _HIDP_LINK_COLLECTION_NODE. - -Arguments: - LinkCollectionNodes - a caller allocated array into which - HidP_GetLinkCollectionNodes will store the information - - LinKCollectionNodesLength - the caller sets this value to the length of the - the array in terms of number of elements. - HidP_GetLinkCollectionNodes sets this value to the actual - number of elements set. The total number of nodes required to - describe this HID device can be found in the - NumberLinkCollectionNodes field in the HIDP_CAPS structure. - ---*/ - -NTSTATUS __stdcall -HidP_GetButtonCaps ( - IN HIDP_REPORT_TYPE ReportType, - OUT PHIDP_BUTTON_CAPS ButtonCaps, - IN OUT PUSHORT ButtonCapsLength, - IN PHIDP_PREPARSED_DATA PreparsedData -); -#define HidP_GetButtonCaps(_Type_, _Caps_, _Len_, _Data_) \ - HidP_GetSpecificButtonCaps (_Type_, 0, 0, 0, _Caps_, _Len_, _Data_) -NTSTATUS __stdcall -HidP_GetSpecificButtonCaps ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, // Optional (0 => ignore) - IN USHORT LinkCollection, // Optional (0 => ignore) - IN USAGE Usage, // Optional (0 => ignore) - OUT PHIDP_BUTTON_CAPS ButtonCaps, - IN OUT PUSHORT ButtonCapsLength, - IN PHIDP_PREPARSED_DATA PreparsedData - ); -/*++ -Description: - HidP_GetButtonCaps returns all the buttons (binary values) that are a part - of the given report type for the Hid device represented by the given - preparsed data. - -Parameters: - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - UsagePage A usage page value used to limit the button caps returned to - those on a given usage page. If set to 0, this parameter is - ignored. Can be used with LinkCollection and Usage parameters - to further limit the number of button caps structures returned. - - LinkCollection HIDP_LINK_COLLECTION node array index used to limit the - button caps returned to those buttons in a given link - collection. If set to 0, this parameter is - ignored. Can be used with UsagePage and Usage parameters - to further limit the number of button caps structures - returned. - - Usage A usage value used to limit the button caps returned to those - with the specified usage value. If set to 0, this parameter - is ignored. Can be used with LinkCollection and UsagePage - parameters to further limit the number of button caps - structures returned. - - ButtonCaps A _HIDP_BUTTON_CAPS array containing information about all the - binary values in the given report. This buffer is provided by - the caller. - - ButtonLength As input, this parameter specifies the length of the - ButtonCaps parameter (array) in number of array elements. - As output, this value is set to indicate how many of those - array elements were filled in by the function. The maximum number of - button caps that can be returned is found in the HIDP_CAPS - structure. If HIDP_STATUS_BUFFER_TOO_SMALL is returned, - this value contains the number of array elements needed to - successfully complete the request. - - PreparsedData The preparsed data returned from HIDCLASS. - - -Return Value -HidP_GetSpecificButtonCaps returns the following error codes: -· HIDP_STATUS_SUCCESS. -· HIDP_STATUS_INVALID_REPORT_TYPE -· HIDP_STATUS_INVALID_PREPARSED_DATA -· HIDP_STATUS_BUFFER_TOO_SMALL (all given entries however have been filled in) -· HIDP_STATUS_USAGE_NOT_FOUND ---*/ - -NTSTATUS __stdcall -HidP_GetValueCaps ( - IN HIDP_REPORT_TYPE ReportType, - OUT PHIDP_VALUE_CAPS ValueCaps, - IN OUT PUSHORT ValueCapsLength, - IN PHIDP_PREPARSED_DATA PreparsedData -); -#define HidP_GetValueCaps(_Type_, _Caps_, _Len_, _Data_) \ - HidP_GetSpecificValueCaps (_Type_, 0, 0, 0, _Caps_, _Len_, _Data_) -NTSTATUS __stdcall -HidP_GetSpecificValueCaps ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, // Optional (0 => ignore) - IN USHORT LinkCollection, // Optional (0 => ignore) - IN USAGE Usage, // Optional (0 => ignore) - OUT PHIDP_VALUE_CAPS ValueCaps, - IN OUT PUSHORT ValueCapsLength, - IN PHIDP_PREPARSED_DATA PreparsedData - ); -/*++ -Description: - HidP_GetValueCaps returns all the values (non-binary) that are a part - of the given report type for the Hid device represented by the given - preparsed data. - -Parameters: - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - UsagePage A usage page value used to limit the value caps returned to - those on a given usage page. If set to 0, this parameter is - ignored. Can be used with LinkCollection and Usage parameters - to further limit the number of value caps structures returned. - - LinkCollection HIDP_LINK_COLLECTION node array index used to limit the - value caps returned to those buttons in a given link - collection. If set to 0, this parameter is - ignored. Can be used with UsagePage and Usage parameters - to further limit the number of value caps structures - returned. - - Usage A usage value used to limit the value caps returned to those - with the specified usage value. If set to 0, this parameter - is ignored. Can be used with LinkCollection and UsagePage - parameters to further limit the number of value caps - structures returned. - - ValueCaps A _HIDP_VALUE_CAPS array containing information about all the - non-binary values in the given report. This buffer is provided - by the caller. - - ValueLength As input, this parameter specifies the length of the ValueCaps - parameter (array) in number of array elements. As output, - this value is set to indicate how many of those array elements - were filled in by the function. The maximum number of - value caps that can be returned is found in the HIDP_CAPS - structure. If HIDP_STATUS_BUFFER_TOO_SMALL is returned, - this value contains the number of array elements needed to - successfully complete the request. - - PreparsedData The preparsed data returned from HIDCLASS. - - -Return Value -HidP_GetValueCaps returns the following error codes: -· HIDP_STATUS_SUCCESS. -· HIDP_STATUS_INVALID_REPORT_TYPE -· HIDP_STATUS_INVALID_PREPARSED_DATA -· HIDP_STATUS_BUFFER_TOO_SMALL (all given entries however have been filled in) -· HIDP_STATUS_USAGE_NOT_FOUND - ---*/ - -NTSTATUS __stdcall -HidP_GetExtendedAttributes ( - IN HIDP_REPORT_TYPE ReportType, - IN USHORT DataIndex, - IN PHIDP_PREPARSED_DATA PreparsedData, - OUT PHIDP_EXTENDED_ATTRIBUTES Attributes, - IN OUT PULONG LengthAttributes - ); -/*++ -Description: - Given a data index from the value or button capabilities of a given control - return any extended attributes for the control if any exist. - -Parameters: - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - DataIndex The data index for the given control, found in the capabilities - structure for that control - - PreparsedData The preparsed data returned from HIDCLASS. - - Attributes Pointer to a buffer into which the extended attribute data will - be copied. - - LengthAttributes Length of the given buffer in bytes. - -Return Value - HIDP_STATUS_SUCCESS - HIDP_STATUS_DATA_INDEX_NOT_FOUND ---*/ - -NTSTATUS __stdcall -HidP_InitializeReportForID ( - IN HIDP_REPORT_TYPE ReportType, - IN UCHAR ReportID, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - - Initialize a report based on the given report ID. - -Parameters: - - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - PreparasedData Preparsed data structure returned by HIDCLASS - - Report Buffer which to set the data into. - - ReportLength Length of Report...Report should be at least as long as the - value indicated in the HIDP_CAPS structure for the device and - the corresponding ReportType - -Return Value - -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal - to the length specified in HIDP_CAPS - structure for the given ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType - ---*/ - -NTSTATUS __stdcall -HidP_SetData ( - IN HIDP_REPORT_TYPE ReportType, - IN PHIDP_DATA DataList, - IN OUT PULONG DataLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - - Please Note: Since usage value arrays deal with multiple fields for - for one usage value, they cannot be used with HidP_SetData - and HidP_GetData. In this case, - HIDP_STATUS_IS_USAGE_VALUE_ARRAY will be returned. - -Parameters: - - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - DataList Array of HIDP_DATA structures that contains the data values - that are to be set into the given report - - DataLength As input, length in array elements of DataList. As output, - contains the number of data elements set on successful - completion or an index into the DataList array to identify - the faulting HIDP_DATA value if an error code is returned. - - PreparasedData Preparsed data structure returned by HIDCLASS - - Report Buffer which to set the data into. - - ReportLength Length of Report...Report should be at least as long as the - value indicated in the HIDP_CAPS structure for the device and - the corresponding ReportType - -Return Value - HidP_SetData returns the following error codes. The report packet will - have all the data set up until the HIDP_DATA structure that caused the - error. DataLength, in the error case, will return this problem index. - -· HIDP_STATUS_SUCCESS -- upon successful insertion of all data - into the report packet. -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_DATA_INDEX_NOT_FOUND -- if a HIDP_DATA structure referenced a - data index that does not exist for this - device's ReportType -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal - to the length specified in HIDP_CAPS - structure for the given ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_IS_USAGE_VALUE_ARRAY -- if one of the HIDP_DATA structures - references a usage value array. - DataLength will contain the index into - the array that was invalid -· HIDP_STATUS_BUTTON_NOT_PRESSED -- if a HIDP_DATA structure attempted - to unset a button that was not already - set in the Report -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- a HIDP_DATA structure was found with - a valid index value but is contained - in a different report than the one - currently being processed -· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough entries in - a given Main Array Item to report all - buttons that have been requested to be - set ---*/ - -NTSTATUS __stdcall -HidP_GetData ( - IN HIDP_REPORT_TYPE ReportType, - OUT PHIDP_DATA DataList, - IN OUT PULONG DataLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - - Please Note: For obvious reasons HidP_SetData and HidP_GetData will not - access UsageValueArrays. - -Parameters: - ReportType One of HidP_Input, HidP_Output, or HidP_Feature. - - DataList Array of HIDP_DATA structures that will receive the data - values that are set in the given report - - DataLength As input, length in array elements of DataList. As output, - contains the number of data elements that were successfully - set by HidP_GetData. The maximum size necessary for DataList - can be determined by calling HidP_MaxDataListLength - - PreparasedData Preparsed data structure returned by HIDCLASS - - Report Buffer which to set the data into. - - ReportLength Length of Report...Report should be at least as long as the - value indicated in the HIDP_CAPS structure for the device and - the corresponding ReportType - -Return Value - HidP_GetData returns the following error codes. - -· HIDP_STATUS_SUCCESS -- upon successful retrieval of all data - from the report packet. -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not equal - to the length specified in HIDP_CAPS - structure for the given ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough array entries in - DataList to store all the indice values - in the given report. DataLength will - contain the number of array entries - required to hold all data ---*/ - -ULONG __stdcall -HidP_MaxDataListLength ( - IN HIDP_REPORT_TYPE ReportType, - IN PHIDP_PREPARSED_DATA PreparsedData - ); -/*++ -Routine Description: - - This function returns the maximum length of HIDP_DATA elements that - HidP_GetData could return for the given report type. - -Parameters: - - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - PreparsedData Preparsed data structure returned by HIDCLASS - -Return Value: - - The length of the data list array required for the HidP_GetData function - call. If an error occurs (either HIDP_STATUS_INVALID_REPORT_TYPE or - HIDP_STATUS_INVALID_PREPARSED_DATA), this function returns 0. - ---*/ - -#define HidP_SetButtons(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) \ - HidP_SetUsages(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) - -NTSTATUS __stdcall -HidP_SetUsages ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN PUSAGE UsageList, - IN OUT PULONG UsageLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - This function sets binary values (buttons) in a report. Given an - initialized packet of correct length, it modifies the report packet so that - each element in the given list of usages has been set in the report packet. - For example, in an output report with 5 LED’s, each with a given usage, - an application could turn on any subset of these lights by placing their - usages in any order into the usage array (UsageList). HidP_SetUsages would, - in turn, set the appropriate bit or add the corresponding byte into the - HID Main Array Item. - - A properly initialized Report packet is one of the correct byte length, - and all zeros. - - NOTE: A packet that has already been set with a call to a HidP_Set routine - can also be passed in. This routine then sets processes the UsageList - in the same fashion but verifies that the ReportID already set in - Report matches the report ID for the given usages. - -Parameters: - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - UsagePage All of the usages in the usage array, which HidP_SetUsages will - set in the report, refer to this same usage page. - If a client wishes to set usages in a report for multiple - usage pages then that client needs to make multiple calls to - HidP_SetUsages for each of the usage pages. - - UsageList A usage array containing the usages that HidP_SetUsages will set in - the report packet. - - UsageLength The length of the given usage array in array elements. - The parser will set this value to the position in the usage - array where it stopped processing. If successful, UsageLength - will be unchanged. In any error condition, this parameter - reflects how many of the usages in the usage list have - actually been set by the parser. This is useful for finding - the usage in the list which caused the error. - - PreparsedData The preparsed data recevied from HIDCLASS - - Report The report packet. - - ReportLength Length of the given report packet...Must be equal to the - value reported in the HIDP_CAPS structure for the device - and corresponding report type. - -Return Value - HidP_SetUsages returns the following error codes. On error, the report packet - will be correct up until the usage element that caused the error. - -· HIDP_STATUS_SUCCESS -- upon successful insertion of all usages - into the report packet. -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if a usage was found that exists in a - different report. If the report is - zero-initialized on entry the first - usage in the list will determine which - report ID is used. Otherwise, the - parser will verify that usage matches - the passed in report's ID -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage does not exist for any - report (no matter what the report ID) - for the given report type. -· HIDP_STATUS_BUFFER_TOO_SMALL -- if there are not enough entries in a - given Main Array Item to list all of - the given usages. The caller needs - to split his request into more than - one call ---*/ - -#define HidP_UnsetButtons(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) \ - HidP_UnsetUsages(Rty, Up, Lco, ULi, ULe, Ppd, Rep, Rle) - -NTSTATUS __stdcall -HidP_UnsetUsages ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN PUSAGE UsageList, - IN OUT PULONG UsageLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - This function unsets (turns off) binary values (buttons) in the report. Given - an initialized packet of correct length, it modifies the report packet so - that each element in the given list of usages has been unset in the - report packet. - - This function is the "undo" operation for SetUsages. If the given usage - is not already set in the Report, it will return an error code of - HIDP_STATUS_BUTTON_NOT_PRESSED. If the button is pressed, HidP_UnsetUsages - will unset the appropriate bit or remove the corresponding index value from - the HID Main Array Item. - - A properly initialized Report packet is one of the correct byte length, - and all zeros.. - - NOTE: A packet that has already been set with a call to a HidP_Set routine - can also be passed in. This routine then processes the UsageList - in the same fashion but verifies that the ReportID already set in - Report matches the report ID for the given usages. - -Parameters: - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - UsagePage All of the usages in the usage array, which HidP_UnsetUsages will - unset in the report, refer to this same usage page. - If a client wishes to unset usages in a report for multiple - usage pages then that client needs to make multiple calls to - HidP_UnsetUsages for each of the usage pages. - - UsageList A usage array containing the usages that HidP_UnsetUsages will - unset in the report packet. - - UsageLength The length of the given usage array in array elements. - The parser will set this value to the position in the usage - array where it stopped processing. If successful, UsageLength - will be unchanged. In any error condition, this parameter - reflects how many of the usages in the usage list have - actually been unset by the parser. This is useful for finding - the usage in the list which caused the error. - - PreparsedData The preparsed data recevied from HIDCLASS - - Report The report packet. - - ReportLength Length of the given report packet...Must be equal to the - value reported in the HIDP_CAPS structure for the device - and corresponding report type. - -Return Value - HidP_UnsetUsages returns the following error codes. On error, the report - packet will be correct up until the usage element that caused the error. - -· HIDP_STATUS_SUCCESS -- upon successful "unsetting" of all usages - in the report packet. -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if a usage was found that exists in a - different report. If the report is - zero-initialized on entry the first - usage in the list will determine which - report ID is used. Otherwise, the - parser will verify that usage matches - the passed in report's ID -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage does not exist for any - report (no matter what the report ID) - for the given report type. -· HIDP_STATUS_BUTTON_NOT_PRESSED -- if a usage corresponds to a button that - is not already set in the given report ---*/ - -#define HidP_GetButtons(Rty, UPa, LCo, ULi, ULe, Ppd, Rep, RLe) \ - HidP_GetUsages(Rty, UPa, LCo, ULi, ULe, Ppd, Rep, RLe) - -NTSTATUS __stdcall -HidP_GetUsages ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - OUT USAGE * UsageList, - IN OUT ULONG * UsageLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); -/*++ - -Routine Description: - This function returns the binary values (buttons) that are set in a HID - report. Given a report packet of correct length, it searches the report - packet for each usage for the given usage page and returns them in the - usage list. - -Parameters: - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - UsagePage All of the usages in the usage list, which HidP_GetUsages will - retrieve in the report, refer to this same usage page. - If the client wishes to get usages in a packet for multiple - usage pages then that client needs to make multiple calls - to HidP_GetUsages. - - LinkCollection An optional value which can limit which usages are returned - in the UsageList to those usages that exist in a specific - LinkCollection. A non-zero value indicates the index into - the HIDP_LINK_COLLECITON_NODE list returned by - HidP_GetLinkCollectionNodes of the link collection the - usage should belong to. A value of 0 indicates this - should value be ignored. - - UsageList The usage array that will contain all the usages found in - the report packet. - - UsageLength The length of the given usage array in array elements. - On input, this value describes the length of the usage list. - On output, HidP_GetUsages sets this value to the number of - usages that was found. Use HidP_MaxUsageListLength to - determine the maximum length needed to return all the usages - that a given report packet may contain. - - PreparsedData Preparsed data structure returned by HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet - - -Return Value - HidP_GetUsages returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully retrieving all the - usages from the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_BUFFER_TOO_SMALL -- if the UsageList is not big enough to - hold all the usages found in the report - packet. If this is returned, the buffer - will contain UsageLength number of - usages. Use HidP_MaxUsageListLength to - find the maximum length needed -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if no usages were found but usages - that match the UsagePage and - LinkCollection specified could be found - in a report with a different report ID -· HIDP_STATUS_USAGE_NOT_FOUND -- if there are no usages in a reports for - the device and ReportType that match the - UsagePage and LinkCollection that were - specified ---*/ - -#define HidP_GetButtonsEx(Rty, LCo, BLi, ULe, Ppd, Rep, RLe) \ - HidP_GetUsagesEx(Rty, LCo, BLi, ULe, Ppd, Rep, RLe) - -NTSTATUS __stdcall -HidP_GetUsagesEx ( - IN HIDP_REPORT_TYPE ReportType, - IN USHORT LinkCollection, // Optional - OUT PUSAGE_AND_PAGE ButtonList, - IN OUT ULONG * UsageLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); - -/*++ - -Routine Description: - This function returns the binary values (buttons) in a HID report. - Given a report packet of correct length, it searches the report packet - for all buttons and returns the UsagePage and Usage for each of the buttons - it finds. - -Parameters: - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - LinkCollection An optional value which can limit which usages are returned - in the ButtonList to those usages that exist in a specific - LinkCollection. A non-zero value indicates the index into - the HIDP_LINK_COLLECITON_NODE list returned by - HidP_GetLinkCollectionNodes of the link collection the - usage should belong to. A value of 0 indicates this - should value be ignored. - - ButtonList An array of USAGE_AND_PAGE structures describing all the - buttons currently ``down'' in the device. - - UsageLength The length of the given array in terms of elements. - On input, this value describes the length of the list. On - output, HidP_GetUsagesEx sets this value to the number of - usages that were found. Use HidP_MaxUsageListLength to - determine the maximum length needed to return all the usages - that a given report packet may contain. - - PreparsedData Preparsed data returned by HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value - HidP_GetUsagesEx returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully retrieving all the - usages from the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_BUFFER_TOO_SMALL -- if ButtonList is not big enough to - hold all the usages found in the report - packet. If this is returned, the buffer - will contain UsageLength number of - usages. Use HidP_MaxUsageListLength to - find the maximum length needed -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- if no usages were found but usages - that match the specified LinkCollection - exist in report with a different report - ID. -· HIDP_STATUS_USAGE_NOT_FOUND -- if there are no usages in any reports that - match the LinkCollection parameter ---*/ - -#define HidP_GetButtonListLength(RTy, UPa, Ppd) \ - HidP_GetUsageListLength(Rty, UPa, Ppd) - -ULONG __stdcall -HidP_MaxUsageListLength ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, // Optional - IN PHIDP_PREPARSED_DATA PreparsedData - ); -/*++ -Routine Description: - This function returns the maximum number of usages that a call to - HidP_GetUsages or HidP_GetUsagesEx could return for a given HID report. - If calling for number of usages returned by HidP_GetUsagesEx, use 0 as - the UsagePage value. - -Parameters: - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - UsagePage Specifies the optional UsagePage to query for. If 0, will - return all the maximum number of usage values that could be - returned for a given ReportType. If non-zero, will return - the maximum number of usages that would be returned for the - ReportType with the given UsagePage. - - PreparsedData Preparsed data returned from HIDCLASS - -Return Value: - The length of the usage list array required for the HidP_GetUsages or - HidP_GetUsagesEx function call. If an error occurs (such as - HIDP_STATUS_INVALID_REPORT_TYPE or HIDP_INVALID_PREPARSED_DATA, this - returns 0. ---*/ - -NTSTATUS __stdcall -HidP_SetUsageValue ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - IN ULONG UsageValue, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); -/*++ -Description: - HidP_SetUsageValue inserts a value into the HID Report Packet in the field - corresponding to the given usage page and usage. HidP_SetUsageValue - casts this value to the appropriate bit length. If a report packet - contains two different fields with the same Usage and UsagePage, - they can be distinguished with the optional LinkCollection field value. - Using this function sets the raw value into the report packet with - no checking done as to whether it actually falls within the logical - minimum/logical maximum range. Use HidP_SetScaledUsageValue for this... - - NOTE: Although the UsageValue parameter is a ULONG, any casting that is - done will preserve or sign-extend the value. The value being set - should be considered a LONG value and will be treated as such by - this function. - -Parameters: - - ReportType One of HidP_Output or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will set the first field - it finds that matches the usage page and - usage. - - Usage The usage whose value HidP_SetUsageValue will set. - - UsageValue The raw value to set in the report buffer. This value must be within - the logical range or if a NULL value this value should be the - most negative value that can be represented by the number of bits - for this field. - - PreparsedData The preparsed data returned for HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value: - HidP_SetUsageValue returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully setting the value - in the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call HidP_SetUsageValue - again with a zero-initizialed report - packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - -NTSTATUS __stdcall -HidP_SetScaledUsageValue ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - IN LONG UsageValue, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN OUT PCHAR Report, - IN ULONG ReportLength - ); - -/*++ -Description: - HidP_SetScaledUsageValue inserts the UsageValue into the HID report packet - in the field corresponding to the given usage page and usage. If a report - packet contains two different fields with the same Usage and UsagePage, - they can be distinguished with the optional LinkCollection field value. - - If the specified field has a defined physical range, this function converts - the physical value specified to the corresponding logical value for the - report. If a physical value does not exist, the function will verify that - the value specified falls within the logical range and set according. - - If the range checking fails but the field has NULL values, the function will - set the field to the defined NULL value (most negative number possible) and - return HIDP_STATUS_NULL. In other words, use this function to set NULL - values for a given field by passing in a value that falls outside the - physical range if it is defined or the logical range otherwise. - - If the field does not support NULL values, an out of range error will be - returned instead. - -Parameters: - - ReportType One of HidP_Output or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will set the first field - it finds that matches the usage page and - usage. - - Usage The usage whose value HidP_SetScaledUsageValue will set. - - UsageValue The value to set in the report buffer. See the routine - description above for the different interpretations of this - value - - PreparsedData The preparsed data returned from HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value: - HidP_SetScaledUsageValue returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully setting the value - in the report packet -· HIDP_STATUS_NULL -- upon successfully setting the value - in the report packet as a NULL value -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_VALUE_OUT_OF_RANGE -- if the value specified failed to fall - within the physical range if it exists - or within the logical range otherwise - and the field specified by the usage - does not allow NULL values -· HIDP_STATUS_BAD_LOG_PHY_VALUES -- if the field has a physical range but - either the logical range is invalid - (max <= min) or the physical range is - invalid -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call - HidP_SetScaledUsageValue again with - a zero-initialized report packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - -NTSTATUS __stdcall -HidP_SetUsageValueArray ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - IN PCHAR UsageValue, - IN USHORT UsageValueByteLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - OUT PCHAR Report, - IN ULONG ReportLength - ); - -/*++ -Routine Descripton: - A usage value array occurs when the last usage in the list of usages - describing a main item must be repeated because there are less usages defined - than there are report counts declared for the given main item. In this case - a single value cap is allocated for that usage and the report count of that - value cap is set to reflect the number of fields to which that usage refers. - - HidP_SetUsageValueArray sets the raw bits for that usage which spans - more than one field in a report. - - NOTE: This function currently does not support value arrays where the - ReportSize for each of the fields in the array is not a multiple - of 8 bits. - - The UsageValue buffer should have the values set as they would appear - in the report buffer. If this function supported non 8-bit multiples - for the ReportSize then caller should format the input buffer so that - each new value begins at the bit immediately following the last bit - of the previous value - -Parameters: - - ReportType One of HidP_Output or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will set the first field - it finds that matches the usage page and - usage. - - Usage The usage whose value array HidP_SetUsageValueArray will set. - - UsageValue The buffer with the values to set into the value array. - The number of BITS required is found by multiplying the - BitSize and ReportCount fields of the Value Cap for this - control. The least significant bit of this control found in the - given report will be placed in the least significan bit location - of the array given (little-endian format), regardless of whether - or not the field is byte alligned or if the BitSize is a multiple - of sizeof (CHAR). - - See the above note for current implementation limitations. - - UsageValueByteLength Length of the UsageValue buffer (in bytes) - - PreparsedData The preparsed data returned from HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value: -· HIDP_STATUS_SUCCESS -- upon successfully setting the value - array in the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_NOT_VALUE_ARRAY -- if the control specified is not a - value array -- a value array will have - a ReportCount field in the - HIDP_VALUE_CAPS structure that is > 1 - Use HidP_SetUsageValue instead -· HIDP_STATUS_BUFFER_TOO_SMALL -- if the size of the passed in buffer with - the values to set is too small (ie. has - fewer values than the number of fields in - the array -· HIDP_STATUS_NOT_IMPLEMENTED -- if the usage value array has field sizes - that are not multiples of 8 bits, this - error code is returned since the function - currently does not handle setting into - such arrays. -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call - HidP_SetUsageValueArray again with - a zero-initialized report packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - - -NTSTATUS __stdcall -HidP_GetUsageValue ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - OUT PULONG UsageValue, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); - -/* -Description - HidP_GetUsageValue retrieves the value from the HID Report for the usage - specified by the combination of usage page, usage and link collection. - If a report packet contains two different fields with the same - Usage and UsagePage, they can be distinguished with the optional - LinkCollection field value. - -Parameters: - - ReportType One of HidP_Input or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will set the first field - it finds that matches the usage page and - usage. - - Usage The usage whose value HidP_GetUsageValue will retrieve - - UsageValue The raw value that is set for the specified field in the report - buffer. This value will either fall within the logical range - or if NULL values are allowed, a number outside the range to - indicate a NULL - - PreparsedData The preparsed data returned for HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value: - HidP_GetUsageValue returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value - from the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_REPORT_DOES_NOT_EXIST -- if there are no reports on this device - for the given ReportType -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call HidP_GetUsageValue - again with a different report packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - - -NTSTATUS __stdcall -HidP_GetScaledUsageValue ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - OUT PLONG UsageValue, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); - -/*++ -Description - HidP_GetScaledUsageValue retrieves a UsageValue from the HID report packet - in the field corresponding to the given usage page and usage. If a report - packet contains two different fields with the same Usage and UsagePage, - they can be distinguished with the optional LinkCollection field value. - - If the specified field has a defined physical range, this function converts - the logical value that exists in the report packet to the corresponding - physical value. If a physical range does not exist, the function will - return the logical value. This function will check to verify that the - logical value in the report falls within the declared logical range. - - When doing the conversion between logical and physical values, this - function assumes a linear extrapolation between the physical max/min and - the logical max/min. (Where logical is the values reported by the device - and physical is the value returned by this function). If the data field - size is less than 32 bits, then HidP_GetScaledUsageValue will sign extend - the value to 32 bits. - - If the range checking fails but the field has NULL values, the function - will set UsageValue to 0 and return HIDP_STATUS_NULL. Otherwise, it - returns a HIDP_STATUS_OUT_OF_RANGE error. - -Parameters: - - ReportType One of HidP_Output or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will retrieve the first - field it finds that matches the usage page - and usage. - - Usage The usage whose value HidP_GetScaledUsageValue will retrieve - - UsageValue The value retrieved from the report buffer. See the routine - description above for the different interpretations of this - value - - PreparsedData The preparsed data returned from HIDCLASS - - Report The report packet. - - ReportLength Length (in bytes) of the given report packet. - - -Return Value: - HidP_GetScaledUsageValue returns the following error codes: - -· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value - from the report packet -· HIDP_STATUS_NULL -- if the report packet had a NULL value - set -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_VALUE_OUT_OF_RANGE -- if the value retrieved from the packet - falls outside the logical range and - the field does not support NULL values -· HIDP_STATUS_BAD_LOG_PHY_VALUES -- if the field has a physical range but - either the logical range is invalid - (max <= min) or the physical range is - invalid -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call - HidP_GetScaledUsageValue with a - different report packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - -NTSTATUS __stdcall -HidP_GetUsageValueArray ( - IN HIDP_REPORT_TYPE ReportType, - IN USAGE UsagePage, - IN USHORT LinkCollection, // Optional - IN USAGE Usage, - OUT PCHAR UsageValue, - IN USHORT UsageValueByteLength, - IN PHIDP_PREPARSED_DATA PreparsedData, - IN PCHAR Report, - IN ULONG ReportLength - ); - -/*++ -Routine Descripton: - A usage value array occurs when the last usage in the list of usages - describing a main item must be repeated because there are less usages defined - than there are report counts declared for the given main item. In this case - a single value cap is allocated for that usage and the report count of that - value cap is set to reflect the number of fields to which that usage refers. - - HidP_GetUsageValueArray returns the raw bits for that usage which spans - more than one field in a report. - - NOTE: This function currently does not support value arrays where the - ReportSize for each of the fields in the array is not a multiple - of 8 bits. - - The UsageValue buffer will have the raw values as they are set - in the report packet. - -Parameters: - - ReportType One of HidP_Input, HidP_Output or HidP_Feature. - - UsagePage The usage page to which the given usage refers. - - LinkCollection (Optional) This value can be used to differentiate - between two fields that may have the same - UsagePage and Usage but exist in different - collections. If the link collection value - is zero, this function will set the first field - it finds that matches the usage page and - usage. - - Usage The usage whose value HidP_GetUsageValueArray will retreive. - - UsageValue A pointer to an array of characters where the value will be - placed. The number of BITS required is found by multiplying the - BitSize and ReportCount fields of the Value Cap for this - control. The least significant bit of this control found in the - given report will be placed in the least significant bit location - of the buffer (little-endian format), regardless of whether - or not the field is byte aligned or if the BitSize is a multiple - of sizeof (CHAR). - - See note above about current implementation limitations - - UsageValueByteLength - the length of the given UsageValue buffer. - - PreparsedData The preparsed data returned by the HIDCLASS - - Report The report packet. - - ReportLength Length of the given report packet. - -Return Value: - -· HIDP_STATUS_SUCCESS -- upon successfully retrieving the value - from the report packet -· HIDP_STATUS_INVALID_REPORT_TYPE -- if ReportType is not valid. -· HIDP_STATUS_INVALID_PREPARSED_DATA -- if PreparsedData is not valid -· HIDP_STATUS_INVALID_REPORT_LENGTH -- the length of the report packet is not - equal to the length specified in - the HIDP_CAPS structure for the given - ReportType -· HIDP_STATUS_NOT_VALUE_ARRAY -- if the control specified is not a - value array -- a value array will have - a ReportCount field in the - HIDP_VALUE_CAPS structure that is > 1 - Use HidP_GetUsageValue instead -· HIDP_STATUS_BUFFER_TOO_SMALL -- if the size of the passed in buffer in - which to return the array is too small - (ie. has fewer values than the number of - fields in the array -· HIDP_STATUS_NOT_IMPLEMENTED -- if the usage value array has field sizes - that are not multiples of 8 bits, this - error code is returned since the function - currently does not handle getting values - from such arrays. -· HIDP_STATUS_INCOMPATIBLE_REPORT_ID -- the specified usage page, usage and - link collection exist but exists in - a report with a different report ID - than the report being passed in. To - set this value, call - HidP_GetUsageValueArray with a - different report packet -· HIDP_STATUS_USAGE_NOT_FOUND -- if the usage page, usage, and link - collection combination does not exist - in any reports for this ReportType ---*/ - -NTSTATUS __stdcall -HidP_UsageListDifference ( - IN PUSAGE PreviousUsageList, - IN PUSAGE CurrentUsageList, - OUT PUSAGE BreakUsageList, - OUT PUSAGE MakeUsageList, - IN ULONG UsageListLength - ); -/*++ -Routine Description: - This function will return the difference between a two lists of usages - (as might be returned from HidP_GetUsages), In other words, it will return - return a list of usages that are in the current list but not the previous - list as well as a list of usages that are in the previous list but not - the current list. - -Parameters: - - PreviousUsageList The list of usages before. - CurrentUsageList The list of usages now. - BreakUsageList Previous - Current. - MakeUsageList Current - Previous. - UsageListLength Represents the length of the usage lists in array - elements. If comparing two lists with a differing - number of array elements, this value should be - the size of the larger of the two lists. Any - zero found with a list indicates an early termination - of the list and any usages found after the first zero - will be ignored. ---*/ - -NTSTATUS __stdcall -HidP_UsageAndPageListDifference ( - IN PUSAGE_AND_PAGE PreviousUsageList, - IN PUSAGE_AND_PAGE CurrentUsageList, - OUT PUSAGE_AND_PAGE BreakUsageList, - OUT PUSAGE_AND_PAGE MakeUsageList, - IN ULONG UsageListLength - ); - -// -// Produce Make or Break Codes -// -typedef enum _HIDP_KEYBOARD_DIRECTION { - HidP_Keyboard_Break, - HidP_Keyboard_Make -} HIDP_KEYBOARD_DIRECTION; - -// -// A bitmap of the current shift state of the keyboard when using the -// below keyboard usages to i8042 translation function. -// -typedef struct _HIDP_KEYBOARD_MODIFIER_STATE { - union { - struct { - ULONG LeftControl: 1; - ULONG LeftShift: 1; - ULONG LeftAlt: 1; - ULONG LeftGUI: 1; - ULONG RightControl: 1; - ULONG RightShift: 1; - ULONG RightAlt: 1; - ULONG RigthGUI: 1; - ULONG CapsLock: 1; - ULONG ScollLock: 1; - ULONG NumLock: 1; - ULONG Reserved: 21; - }; - ULONG ul; - }; - -} HIDP_KEYBOARD_MODIFIER_STATE, * PHIDP_KEYBOARD_MODIFIER_STATE; - -// -// A call back function to give the i8042 scan codes to the caller of -// the below translation function. -// -typedef BOOLEAN (* PHIDP_INSERT_SCANCODES) ( - IN PVOID Context, // Some caller supplied context. - IN PCHAR NewScanCodes, // A list of i8042 scan codes. - IN ULONG Length // the length of the scan codes. - ); - -NTSTATUS __stdcall -HidP_TranslateUsageAndPagesToI8042ScanCodes ( - IN PUSAGE_AND_PAGE ChangedUsageList, - IN ULONG UsageListLength, - IN HIDP_KEYBOARD_DIRECTION KeyAction, - IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, - IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, - IN PVOID InsertCodesContext - ); -/*++ -Routine Description: -Parameters: ---*/ - -NTSTATUS __stdcall -HidP_TranslateUsagesToI8042ScanCodes ( - IN PUSAGE ChangedUsageList, - IN ULONG UsageListLength, - IN HIDP_KEYBOARD_DIRECTION KeyAction, - IN OUT PHIDP_KEYBOARD_MODIFIER_STATE ModifierState, - IN PHIDP_INSERT_SCANCODES InsertCodesProcedure, - IN PVOID InsertCodesContext - ); -/*++ -Routine Description: -Parameters: ---*/ - - - -// -// Define NT Status codes with Facility Code of FACILITY_HID_ERROR_CODE -// - -// FACILITY_HID_ERROR_CODE defined in ntstatus.h -#ifndef FACILITY_HID_ERROR_CODE -#define FACILITY_HID_ERROR_CODE 0x11 -#endif - -#define HIDP_ERROR_CODES(SEV, CODE) \ - ((NTSTATUS) (((SEV) << 28) | (FACILITY_HID_ERROR_CODE << 16) | (CODE))) - -#define HIDP_STATUS_SUCCESS (HIDP_ERROR_CODES(0x0,0)) -#define HIDP_STATUS_NULL (HIDP_ERROR_CODES(0x8,1)) -#define HIDP_STATUS_INVALID_PREPARSED_DATA (HIDP_ERROR_CODES(0xC,1)) -#define HIDP_STATUS_INVALID_REPORT_TYPE (HIDP_ERROR_CODES(0xC,2)) -#define HIDP_STATUS_INVALID_REPORT_LENGTH (HIDP_ERROR_CODES(0xC,3)) -#define HIDP_STATUS_USAGE_NOT_FOUND (HIDP_ERROR_CODES(0xC,4)) -#define HIDP_STATUS_VALUE_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,5)) -#define HIDP_STATUS_BAD_LOG_PHY_VALUES (HIDP_ERROR_CODES(0xC,6)) -#define HIDP_STATUS_BUFFER_TOO_SMALL (HIDP_ERROR_CODES(0xC,7)) -#define HIDP_STATUS_INTERNAL_ERROR (HIDP_ERROR_CODES(0xC,8)) -#define HIDP_STATUS_I8042_TRANS_UNKNOWN (HIDP_ERROR_CODES(0xC,9)) -#define HIDP_STATUS_INCOMPATIBLE_REPORT_ID (HIDP_ERROR_CODES(0xC,0xA)) -#define HIDP_STATUS_NOT_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xB)) -#define HIDP_STATUS_IS_VALUE_ARRAY (HIDP_ERROR_CODES(0xC,0xC)) -#define HIDP_STATUS_DATA_INDEX_NOT_FOUND (HIDP_ERROR_CODES(0xC,0xD)) -#define HIDP_STATUS_DATA_INDEX_OUT_OF_RANGE (HIDP_ERROR_CODES(0xC,0xE)) -#define HIDP_STATUS_BUTTON_NOT_PRESSED (HIDP_ERROR_CODES(0xC,0xF)) -#define HIDP_STATUS_REPORT_DOES_NOT_EXIST (HIDP_ERROR_CODES(0xC,0x10)) -#define HIDP_STATUS_NOT_IMPLEMENTED (HIDP_ERROR_CODES(0xC,0x20)) - -// -// We blundered this status code. -// -#define HIDP_STATUS_I8242_TRANS_UNKNOWN HIDP_STATUS_I8042_TRANS_UNKNOWN - -#include - -#endif diff --git a/winsrc/include/hidsdi.h b/winsrc/include/hidsdi.h deleted file mode 100644 index d0db806b..00000000 --- a/winsrc/include/hidsdi.h +++ /dev/null @@ -1,412 +0,0 @@ -/*++ - -Copyright (c) 1996 Microsoft Corporation - -Module Name: - - HIDSDI.H - -Abstract: - - This module contains the PUBLIC definitions for the - code that implements the HID dll. - -Environment: - - Kernel & user mode - ---*/ - - -#ifndef _HIDSDI_H -#define _HIDSDI_H - -#include - -//#include "wtypes.h" - -//#include -//#include -//#include - -typedef LONG NTSTATUS; -#include "hidusage.h" -#include "hidpi.h" - -typedef struct _HIDD_CONFIGURATION { - PVOID cookie; - ULONG size; - ULONG RingBufferSize; -} HIDD_CONFIGURATION, *PHIDD_CONFIGURATION; - -typedef struct _HIDD_ATTRIBUTES { - ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES) - - // - // Vendor ids of this hid device - // - USHORT VendorID; - USHORT ProductID; - USHORT VersionNumber; - - // - // Additional fields will be added to the end of this structure. - // -} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES; - - -BOOLEAN __stdcall -HidD_GetAttributes ( - IN HANDLE HidDeviceObject, - OUT PHIDD_ATTRIBUTES Attributes - ); -/*++ -Routine Description: - Fill in the given HIDD_ATTRIBUTES structure with the attributes of the - given hid device. - ---*/ - - -void __stdcall -HidD_GetHidGuid ( - OUT LPGUID HidGuid - ); - -BOOLEAN __stdcall -HidD_GetPreparsedData ( - IN HANDLE HidDeviceObject, - OUT PHIDP_PREPARSED_DATA * PreparsedData - ); -/*++ -Routine Description: - Given a handle to a valid Hid Class Device Object, retrieve the preparsed - data for the device. This routine will allocate the appropriately - sized buffer to hold this preparsed data. It is up to client to call - HidP_FreePreparsedData to free the memory allocated to this structure when - it is no longer needed. - -Arguments: - HidDeviceObject A handle to a Hid Device that the client obtains using - a call to CreateFile on a valid Hid device string name. - The string name can be obtained using standard PnP calls. - - PreparsedData An opaque data structure used by other functions in this - library to retrieve information about a given device. - -Return Value: - TRUE if successful. - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_FreePreparsedData ( - IN PHIDP_PREPARSED_DATA PreparsedData - ); - -BOOLEAN __stdcall -HidD_FlushQueue ( - IN HANDLE HidDeviceObject - ); -/*++ -Routine Description: - Flush the input queue for the given HID device. - -Arguments: - HidDeviceObject A handle to a Hid Device that the client obtains using - a call to CreateFile on a valid Hid device string name. - The string name can be obtained using standard PnP calls. - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetConfiguration ( - IN HANDLE HidDeviceObject, - OUT PHIDD_CONFIGURATION Configuration, - IN ULONG ConfigurationLength - ); -/*++ -Routine Description: - Get the configuration information for this Hid device - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Configuration A configuration structure. HidD_GetConfiguration MUST - be called before the configuration can be modified and - set using HidD_SetConfiguration - - ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this - parameter, we can later increase the length of the - configuration array and not break older apps. - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_SetConfiguration ( - IN HANDLE HidDeviceObject, - IN PHIDD_CONFIGURATION Configuration, - IN ULONG ConfigurationLength - ); -/*++ -Routine Description: - Set the configuration information for this Hid device... - - NOTE: HidD_GetConfiguration must be called to retrieve the current - configuration information before this information can be modified - and set. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Configuration A configuration structure. HidD_GetConfiguration MUST - be called before the configuration can be modified and - set using HidD_SetConfiguration - - ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this - parameter, we can later increase the length of the - configuration array and not break older apps. - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetFeature ( - IN HANDLE HidDeviceObject, - OUT PVOID ReportBuffer, - IN ULONG ReportBufferLength - ); -/*++ -Routine Description: - Retrieve a feature report from a HID device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - ReportBuffer The buffer that the feature report should be placed - into. The first byte of the buffer should be set to - the report ID of the desired report - - ReportBufferLength The size (in bytes) of ReportBuffer. This value - should be greater than or equal to the - FeatureReportByteLength field as specified in the - HIDP_CAPS structure for the device -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_SetFeature ( - IN HANDLE HidDeviceObject, - IN PVOID ReportBuffer, - IN ULONG ReportBufferLength - ); -/*++ -Routine Description: - Send a feature report to a HID device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - ReportBuffer The buffer of the feature report to send to the device - - ReportBufferLength The size (in bytes) of ReportBuffer. This value - should be greater than or equal to the - FeatureReportByteLength field as specified in the - HIDP_CAPS structure for the device -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetNumInputBuffers ( - IN HANDLE HidDeviceObject, - OUT PULONG NumberBuffers - ); -/*++ -Routine Description: - This function returns the number of input buffers used by the specified - file handle to the Hid device. Each file object has a number of buffers - associated with it to queue reports read from the device but which have - not yet been read by the user-mode app with a handle to that device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - NumberBuffers Number of buffers currently being used for this file - handle to the Hid device - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_SetNumInputBuffers ( - IN HANDLE HidDeviceObject, - OUT ULONG NumberBuffers - ); -/*++ - -Routine Description: - This function sets the number of input buffers used by the specified - file handle to the Hid device. Each file object has a number of buffers - associated with it to queue reports read from the device but which have - not yet been read by the user-mode app with a handle to that device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - NumberBuffers New number of buffers to use for this file handle to - the Hid device - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetPhysicalDescriptor ( - IN HANDLE HidDeviceObject, - OUT PVOID Buffer, - IN ULONG BufferLength - ); -/*++ -Routine Description: - This function retrieves the raw physical descriptor for the specified - Hid device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Buffer Buffer which on return will contain the physical - descriptor if one exists for the specified device - handle - - BufferLength Length of buffer (in bytes) - - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetManufacturerString ( - IN HANDLE HidDeviceObject, - OUT PVOID Buffer, - IN ULONG BufferLength - ); -/*++ -Routine Description: - This function retrieves the manufacturer string from the specified - Hid device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Buffer Buffer which on return will contain the manufacturer - string returned from the device. This string is a - wide-character string - - BufferLength Length of Buffer (in bytes) - - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetProductString ( - IN HANDLE HidDeviceObject, - OUT PVOID Buffer, - IN ULONG BufferLength - ); -/*++ -Routine Description: - This function retrieves the product string from the specified - Hid device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Buffer Buffer which on return will contain the product - string returned from the device. This string is a - wide-character string - - BufferLength Length of Buffer (in bytes) - - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetIndexedString ( - IN HANDLE HidDeviceObject, - IN ULONG StringIndex, - OUT PVOID Buffer, - IN ULONG BufferLength - ); -/*++ -Routine Description: - This function retrieves a string from the specified Hid device that is - specified with a certain string index. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - StringIndex Index of the string to retrieve - - Buffer Buffer which on return will contain the product - string returned from the device. This string is a - wide-character string - - BufferLength Length of Buffer (in bytes) - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - -BOOLEAN __stdcall -HidD_GetSerialNumberString ( - IN HANDLE HidDeviceObject, - OUT PVOID Buffer, - IN ULONG BufferLength - ); -/*++ -Routine Description: - This function retrieves the serial number string from the specified - Hid device. - -Arguments: - HidDeviceObject A handle to a Hid Device Object. - - Buffer Buffer which on return will contain the serial number - string returned from the device. This string is a - wide-character string - - BufferLength Length of Buffer (in bytes) - -Return Value: - TRUE if successful - FALSE otherwise -- Use GetLastError() to get extended error information ---*/ - - -#include - -#endif diff --git a/winsrc/include/hidusage.h b/winsrc/include/hidusage.h deleted file mode 100644 index 4ea9dd12..00000000 --- a/winsrc/include/hidusage.h +++ /dev/null @@ -1,263 +0,0 @@ -/*++ - -Copyright (c) 1996, 1997 Microsoft Corporation - -Module Name: - - HIDUSAGE.H - -Abstract: - - Public Definitions of HID USAGES. - -Environment: - - Kernel & user mode - ---*/ - -#ifndef __HIDUSAGE_H__ -#define __HIDUSAGE_H__ - -// -// Usage Pages -// - -typedef USHORT USAGE, *PUSAGE; - -#define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01) -#define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02) -#define HID_USAGE_PAGE_VR ((USAGE) 0x03) -#define HID_USAGE_PAGE_SPORT ((USAGE) 0x04) -#define HID_USAGE_PAGE_GAME ((USAGE) 0x05) -#define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07) -#define HID_USAGE_PAGE_LED ((USAGE) 0x08) -#define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09) -#define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A) -#define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B) -#define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C) -#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D) -#define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10) -#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14) - - -// -// Usages from Generic Desktop Page (0x01) -// - -#define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01) -#define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02) -#define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04) -#define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05) -#define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06) -#define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07) -#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80) - -#define HID_USAGE_GENERIC_X ((USAGE) 0x30) -#define HID_USAGE_GENERIC_Y ((USAGE) 0x31) -#define HID_USAGE_GENERIC_Z ((USAGE) 0x32) -#define HID_USAGE_GENERIC_RX ((USAGE) 0x33) -#define HID_USAGE_GENERIC_RY ((USAGE) 0x34) -#define HID_USAGE_GENERIC_RZ ((USAGE) 0x35) -#define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36) -#define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37) -#define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38) -#define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39) -#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A) -#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B) -#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C) -#define HID_USAGE_GENERIC_VX ((USAGE) 0x40) -#define HID_USAGE_GENERIC_VY ((USAGE) 0x41) -#define HID_USAGE_GENERIC_VZ ((USAGE) 0x42) -#define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43) -#define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44) -#define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45) -#define HID_USAGE_GENERIC_VNO ((USAGE) 0x46) -#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81) -#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82) -#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83) -#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84) -#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85) -#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86) -#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87) -#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88) -#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89) -#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A) -#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B) -#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C) -#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D) - -// -// Usages from Simulation Controls Page (0x02) -// - -#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA) -#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB) - -// -// Virtual Reality Controls Page (0x03) -// - - -// -// Sport Controls Page (0x04) -// - - -// -// Game Controls Page (0x05) -// - - -// -// Keyboard/Keypad Page (0x07) -// - - // Error "keys" -#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00) -#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01) -#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02) -#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03) - - // Letters -#define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04) -#define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D) - // Numbers -#define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E) -#define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27) - // Modifier Keys -#define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0) -#define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1) -#define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2) -#define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3) -#define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4) -#define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5) -#define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6) -#define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7) -#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47) -#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53) -#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39) - // Funtion keys -#define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A) -#define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45) - -#define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28) -#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29) -#define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A) - -#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46) - -// and hundreds more... - -// -// LED Page (0x08) -// - -#define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01) -#define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02) -#define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03) -#define HID_USAGE_LED_COMPOSE ((USAGE) 0x04) -#define HID_USAGE_LED_KANA ((USAGE) 0x05) -#define HID_USAGE_LED_POWER ((USAGE) 0x06) -#define HID_USAGE_LED_SHIFT ((USAGE) 0x07) -#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08) -#define HID_USAGE_LED_MUTE ((USAGE) 0x09) -#define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A) -#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B) -#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C) -#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D) -#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E) -#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F) -#define HID_USAGE_LED_REPEAT ((USAGE) 0x10) -#define HID_USAGE_LED_STEREO ((USAGE) 0x11) -#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12) -#define HID_USAGE_LED_SPINNING ((USAGE) 0x13) -#define HID_USAGE_LED_CAV ((USAGE) 0x14) -#define HID_USAGE_LED_CLV ((USAGE) 0x15) -#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16) -#define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17) -#define HID_USAGE_LED_RING ((USAGE) 0x18) -#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19) -#define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A) -#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B) -#define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C) -#define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D) -#define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E) -#define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F) -#define HID_USAGE_LED_HOLD ((USAGE) 0x20) -#define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21) -#define HID_USAGE_LED_COVERAGE ((USAGE) 0x22) -#define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23) -#define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24) -#define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25) -#define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26) -#define HID_USAGE_LED_STAND_BY ((USAGE) 0x27) -#define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28) -#define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29) -#define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A) -#define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B) -#define HID_USAGE_LED_BUSY ((USAGE) 0x2C) -#define HID_USAGE_LED_READY ((USAGE) 0x2D) -#define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E) -#define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F) -#define HID_USAGE_LED_REMOTE ((USAGE) 0x30) -#define HID_USAGE_LED_FORWARD ((USAGE) 0x31) -#define HID_USAGE_LED_REVERSE ((USAGE) 0x32) -#define HID_USAGE_LED_STOP ((USAGE) 0x33) -#define HID_USAGE_LED_REWIND ((USAGE) 0x34) -#define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35) -#define HID_USAGE_LED_PLAY ((USAGE) 0x36) -#define HID_USAGE_LED_PAUSE ((USAGE) 0x37) -#define HID_USAGE_LED_RECORD ((USAGE) 0x38) -#define HID_USAGE_LED_ERROR ((USAGE) 0x39) -#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A) -#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B) -#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C) -#define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D) -#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E) -#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F) -#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40) -#define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41) -#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42) -#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43) -#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44) -#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45) -#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46) -#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47) -#define HID_USAGE_LED_RED ((USAGE) 0x48) -#define HID_USAGE_LED_GREEN ((USAGE) 0x49) -#define HID_USAGE_LED_AMBER ((USAGE) 0x4A) -#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x3B) - -// -// Button Page (0x09) -// -// There is no need to label these usages. -// - - -// -// Ordinal Page (0x0A) -// -// There is no need to label these usages. -// - - -// -// Telephony Device Page (0x0B) -// - -#define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01) -#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02) -#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03) -#define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04) -#define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05) -#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06) -#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07) - -// -// and others... -// - - -#endif diff --git a/winsrc/prox.cpp b/winsrc/prox.cpp deleted file mode 100644 index 4b80e3cc..00000000 --- a/winsrc/prox.cpp +++ /dev/null @@ -1,580 +0,0 @@ -#include -#include -#include -#include -#include -extern "C" { -#include "include/hidsdi.h" -#include "include/hidpi.h" -} - -#include "prox.h" - -#define OUR_VID 0x9ac4 -#define OUR_PID 0x4b8f -#define bzero(b,len) (memset((b), '\0', (len)), (void) 0) - -int offline = 0; -HANDLE UsbHandle; - -static void ShowError(void) -{ - char buf[1024]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, - buf, sizeof(buf), NULL); - printf("ERROR: %s", buf); -} - -static BOOL UsbConnect(void) -{ - typedef void (__stdcall *GetGuidProc)(GUID *); - typedef BOOLEAN (__stdcall *GetAttrProc)(HANDLE, HIDD_ATTRIBUTES *); - typedef BOOLEAN (__stdcall *GetPreparsedProc)(HANDLE, - PHIDP_PREPARSED_DATA *); - typedef NTSTATUS (__stdcall *GetCapsProc)(PHIDP_PREPARSED_DATA, PHIDP_CAPS); - GetGuidProc getGuid; - GetAttrProc getAttr; - GetPreparsedProc getPreparsed; - GetCapsProc getCaps; - - HMODULE h = LoadLibrary("hid.dll"); - getGuid = (GetGuidProc)GetProcAddress(h, "HidD_GetHidGuid"); - getAttr = (GetAttrProc)GetProcAddress(h, "HidD_GetAttributes"); - getPreparsed = (GetPreparsedProc)GetProcAddress(h, "HidD_GetPreparsedData"); - getCaps = (GetCapsProc)GetProcAddress(h, "HidP_GetCaps"); - - GUID hidGuid; - getGuid(&hidGuid); - - HDEVINFO devInfo; - devInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL, - DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); - - SP_DEVICE_INTERFACE_DATA devInfoData; - devInfoData.cbSize = sizeof(devInfoData); - - int i; - for(i = 0;; i++) { - if(!SetupDiEnumDeviceInterfaces(devInfo, 0, &hidGuid, i, &devInfoData)) - { - if(GetLastError() != ERROR_NO_MORE_ITEMS) { -// printf("SetupDiEnumDeviceInterfaces failed\n"); - } -// printf("done list\n"); - SetupDiDestroyDeviceInfoList(devInfo); - return FALSE; - } - -// printf("item %d:\n", i); - - DWORD sizeReqd = 0; - if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData, - NULL, 0, &sizeReqd, NULL)) - { - if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { -// printf("SetupDiGetDeviceInterfaceDetail (0) failed\n"); - continue; - } - } - - SP_DEVICE_INTERFACE_DETAIL_DATA *devInfoDetailData = - (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(sizeReqd); - devInfoDetailData->cbSize = sizeof(*devInfoDetailData); - - if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData, - devInfoDetailData, 87, NULL, NULL)) - { -// printf("SetupDiGetDeviceInterfaceDetail (1) failed\n"); - continue; - } - - char *path = devInfoDetailData->DevicePath; - - UsbHandle = CreateFile(path, /*GENERIC_READ |*/ GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - - if(UsbHandle == INVALID_HANDLE_VALUE) { - ShowError(); -// printf("CreateFile failed: for '%s'\n", path); - continue; - } - - HIDD_ATTRIBUTES attr; - attr.Size = sizeof(attr); - if(!getAttr(UsbHandle, &attr)) { - ShowError(); -// printf("HidD_GetAttributes failed\n"); - continue; - } - -// printf("VID: %04x PID %04x\n", attr.VendorID, attr.ProductID); - - if(attr.VendorID != OUR_VID || attr.ProductID != OUR_PID) { - CloseHandle(UsbHandle); -// printf(" nope, not us\n"); - continue; - } - -// printf ("got it!\n"); - CloseHandle(UsbHandle); - - UsbHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - - if(UsbHandle == INVALID_HANDLE_VALUE) { - ShowError(); -// printf("Error, couldn't open our own handle as desired.\n"); - return FALSE; - } - - PHIDP_PREPARSED_DATA pp; - getPreparsed(UsbHandle, &pp); - HIDP_CAPS caps; - - if(getCaps(pp, &caps) != HIDP_STATUS_SUCCESS) { -// printf("getcaps failed\n"); - return FALSE; - } - -// printf("input/out report %d/%d\n", caps.InputReportByteLength, -// caps.OutputReportByteLength); - - - return TRUE; - } - return FALSE; -} - -BOOL ReceiveCommandPoll(UsbCommand *c) -{ - static BOOL ReadInProgress = FALSE; - static OVERLAPPED Ov; - static BYTE Buf[65]; - static DWORD HaveRead; - - if(!ReadInProgress) { - memset(&Ov, 0, sizeof(Ov)); - ReadFile(UsbHandle, Buf, 65, &HaveRead, &Ov); - if(GetLastError() != ERROR_IO_PENDING) { - ShowError(); - exit(-1); - } - ReadInProgress = TRUE; - } - - if(HasOverlappedIoCompleted(&Ov)) { - ReadInProgress = FALSE; - - if(!GetOverlappedResult(UsbHandle, &Ov, &HaveRead, FALSE)) { - ShowError(); - exit(-1); - } - - memcpy(c, Buf+1, 64); - - return TRUE; - } else { - return FALSE; - } -} - -void ReceiveCommand(UsbCommand *c) -{ - while(!ReceiveCommandPoll(c)) { - Sleep(0); - } -} - -void SendCommand(UsbCommand *c, BOOL wantAck) -{ - BYTE buf[65]; - buf[0] = 0; - memcpy(buf+1, c, 64); - - DWORD written; - OVERLAPPED ov; - - memset(&ov, 0, sizeof(ov)); - WriteFile(UsbHandle, buf, 65, &written, &ov); - if(GetLastError() != ERROR_IO_PENDING) { - ShowError(); - exit(-1); - } - - while(!HasOverlappedIoCompleted(&ov)) { - Sleep(0); - } - - if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) { - ShowError(); - exit(-1); - } - - if(wantAck) { - UsbCommand ack; - ReceiveCommand(&ack); - if(ack.cmd != CMD_ACK) { - printf("bad ACK\n"); - exit(-1); - } - } -} - -static DWORD ExpectedAddr; -static BYTE QueuedToSend[256]; -static BOOL AllWritten; -#define PHYSICAL_FLASH_START 0x100000 - -struct partition { - int start; - int end; - int precious; - const char *name; -}; -struct partition partitions[] = { - {0x100000, 0x102000, 1, "bootrom"}, - {0x102000, 0x110000, 0, "fpga"}, - {0x110000, 0x140000, 0, "os"}, -}; - -/* If translate is set, subtract PHYSICAL_FLASH_START to translate for old - * bootroms. - */ -static void FlushPrevious(int translate) -{ - UsbCommand c; - memset(&c, 0, sizeof(c)); - -// printf("expected = %08x flush, ", ExpectedAddr); - - int i; - for(i = 0; i < 240; i += 48) { - c.cmd = CMD_SETUP_WRITE; - memcpy(c.d.asBytes, QueuedToSend+i, 48); - c.ext1 = (i/4); - SendCommand(&c, TRUE); - } - - c.cmd = CMD_FINISH_WRITE; - c.ext1 = (ExpectedAddr-1) & (~255); - if(translate) { - c.ext1 -= PHYSICAL_FLASH_START; - } - printf("Flashing address: %08x\r", c.ext1); - memcpy(c.d.asBytes, QueuedToSend+240, 16); - SendCommand(&c, TRUE); - - AllWritten = TRUE; -} - -/* Where must be between start_addr (inclusive) and end_addr (exclusive). - */ -static void GotByte(int where, BYTE which, int start_addr, int end_addr, int translate) -{ - AllWritten = FALSE; - - if(where < start_addr || where >= end_addr) { - printf("bad: got byte at %08x, outside of range %08x-%08x\n", where, start_addr, end_addr); - exit(-1); - } - - if(where != ExpectedAddr) { - printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr); - exit(-1); - } - QueuedToSend[where & 255] = which; - ExpectedAddr++; - - if((where & 255) == 255) { - // we have completed a full page - FlushPrevious(translate); - } -} - -static int HexVal(int c) -{ - c = tolower(c); - if(c >= '0' && c <= '9') { - return c - '0'; - } else if(c >= 'a' && c <= 'f') { - return (c - 'a') + 10; - } else { - printf("bad hex digit '%c'\n", c); - exit(-1); - } -} - -static BYTE HexByte(char *s) -{ - return (HexVal(s[0]) << 4) | HexVal(s[1]); -} - -static void LoadFlashFromSRecords(const char *file, int start_addr, int end_addr, int translate) -{ - ExpectedAddr = start_addr; - - FILE *f = fopen(file, "r"); - if(!f) { - printf("couldn't open file\n"); - exit(-1); - } - - char line[512]; - while(fgets(line, sizeof(line), f)) { - if(memcmp(line, "S3", 2)==0) { - char *s = line + 2; - int len = HexByte(s) - 5; - s += 2; - - char addrStr[9]; - memcpy(addrStr, s, 8); - addrStr[8] = '\0'; - DWORD addr; - sscanf(addrStr, "%x", &addr); - s += 8; - - /* Accept files that are located at PHYSICAL_FLASH_START, and files that are located at 0 */ - if(addr < PHYSICAL_FLASH_START) - addr += PHYSICAL_FLASH_START; - - int i; - for(i = 0; i < len; i++) { - while((addr+i) > ExpectedAddr) { - GotByte(ExpectedAddr, 0xff, start_addr, end_addr, translate); - } - GotByte(addr+i, HexByte(s), start_addr, end_addr, translate); - s += 2; - } - } - } - - if(!AllWritten) FlushPrevious(translate); - - fclose(f); - printf("\ndone.\n"); -} - -static int PrepareFlash(struct partition *p, const char *filename, unsigned int state) -{ - int translate = 0; - if(state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { - UsbCommand c; - c.cmd = CMD_START_FLASH; - c.ext1 = p->start; - c.ext2 = p->end; - - /* Only send magic when flashing bootrom */ - if(p->precious) { - c.ext3 = START_FLASH_MAGIC; - } else { - c.ext3 = 0; - } - SendCommand(&c, TRUE); - translate = 0; - } 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"); - translate = 1; - } - - LoadFlashFromSRecords(filename, p->start, p->end, translate); - return 1; -} - -static unsigned int GetProxmarkState(void) -{ - unsigned int state = 0; - - UsbCommand c; - c.cmd = CMD_DEVICE_INFO; - SendCommand(&c, FALSE); - - 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.ext1; - break; - default: - fprintf(stderr, "Couldn't get proxmark state, bad response type: 0x%04X\n", resp.cmd); - exit(-1); - break; - } - -#if 0 - if(state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) printf("New bootrom present\n"); - if(state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT) printf("New osimage present\n"); - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) printf("Currently in bootrom\n"); - if(state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) printf("Currently in OS\n"); -#endif - - return state; -} - -static 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, FALSE); - 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, FALSE); - fprintf(stderr,"(Press and hold down button NOW if your bootloader requires it)\n"); - fprintf(stderr,"Waiting for Proxmark to reappear on USB... "); - } - - - Sleep(1000); - - while(!UsbConnect()) { Sleep(1000); } - fprintf(stderr,"Found.\n"); - - return GetProxmarkState(); - } - - return 0; -} - -static void usage(char **argv) -{ - int i; - printf("Usage: %s gui\n", argv[0]); - printf(" %s offline\n", argv[0]); - printf(" %s areas file.s19\n", argv[0]); - printf(" Known areas are:"); - for(i=0; i<(sizeof(partitions)/sizeof(partitions[0])); i++) { - fprintf(stderr, " %s", partitions[i].name); - } - - printf("\n"); -} - -/* On first call, have *offset = -1, *length = 0; */ -static int find_next_area(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; -} - -int main(int argc, char **argv) -{ - int i = 0; - - if(argc < 2) { - usage(argv); - exit(-1); - } - - // Only do this if NOT in offline mode - if (strcmp(argv[1], "offline")) - { - for(;;) { - if(UsbConnect()) { - break; - } - if(i == 0) { - printf("...no device connected, polling for it now\n"); - } - if(i > 50000) { - printf("Could not connect to USB device; exiting.\n"); - return -1; - } - i++; - Sleep(5); - } - } - - if(strcmp(argv[1], "gui")==0) { - ShowGui(); - } else if(strcmp(argv[1], "offline")==0) { - offline = 1; - ShowGui(); - } - - /* 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); - } - - unsigned int state = EnterFlashState(); - - if( !(state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) ) { - fprintf(stderr, "Proxmark would not enter flash state, abort\n"); - exit(-1); - } - - 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++; - } - - return 0; -} diff --git a/winsrc/prox.h b/winsrc/prox.h deleted file mode 100644 index aeb6dfea..00000000 --- a/winsrc/prox.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef __PROX_H -#define __PROX_H - -#include "../include/usb_cmd.h" - -// prox.cpp -void ReceiveCommand(UsbCommand *c); -BOOL ReceiveCommandPoll(UsbCommand *c); -void SendCommand(UsbCommand *c, BOOL wantAck); - -// gui.cpp -void ShowGui(); -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(BYTE *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 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 WORD Iso15693Crc(BYTE *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