From 03ad2693ce0efa121655802d8d0da8150b9c3f70 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Wed, 23 Jun 2021 04:55:50 +0200 Subject: [PATCH] proto parsing + weirdness highlight --- Makefile | 4 +- libftfake.c | 34 +++++++- libftfake_hl.h | 220 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 4 deletions(-) create mode 100644 libftfake_hl.h diff --git a/Makefile b/Makefile index 7ac56c7..48dcce3 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ all: libftfake.so dumpee libsqfake.so ftdidrv libsqfake.so: libsqfake.c $(CC) -shared -fPIC -Wall -Wextra -Wno-unused-parameter -std=gnu11 -pipe -o $@ $< -libftfake.so: libftfake.c - $(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra +libftfake.so: libftfake.c libftfake_hl.h + $(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra -lm dumpee: dumpee.c $(CC) -o "$@" "$<" -L../build/ -I. -lftd2xx -Wl,-rpath=../build -Wall -Wextra diff --git a/libftfake.c b/libftfake.c index adb3cdf..1ff75db 100644 --- a/libftfake.c +++ b/libftfake.c @@ -8,6 +8,9 @@ #include "ftd2xx.h" +#define HIGHLEVEL +#include "libftfake_hl.h" + static void* libftd2xx; static void lib_open(void) { static bool opened = false; @@ -74,7 +77,9 @@ FT_STATUS FT_GetBitMode(FT_HANDLE ftHandle, PUCHAR pucMode) { FT_STATUS FT_GetQueueStatus(FT_HANDLE ftHandle, DWORD* dwRxBytes) { bind(FT_STATUS, (FT_HANDLE, DWORD*), ftHandle, dwRxBytes); // responsible for lots of spam +#ifndef HIGHLEVEL printf("FT_GetSqueueStatus(%p, &0x%x) = %d\n", ftHandle, *dwRxBytes, rv); +#endif return rv; } @@ -84,6 +89,7 @@ FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) { // * fn(nulterm array to strings, &numdevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER) // * fn(null??, charbuf, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER); // * fn(numdev, NULL, FT_LIST_NUMBER_ONLY); +#ifndef HIGHLEVEL printf("FT_ListDevices(%p, %p, 0x%08x) = %d\n", pArg1, pArg2, flags, rv); if (flags & FT_LIST_NUMBER_ONLY) { if (pArg2) printf(" W! pArg2 != null!\n"); @@ -102,6 +108,7 @@ FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) { } else if (flags & FT_LIST_BY_INDEX) { printf(" W! FT_LIST_BY_INDEX not impl\n"); } else printf(" W! unk flags!\n"); +#endif return rv; } @@ -120,9 +127,21 @@ FT_STATUS FT_OpenEx(PVOID pArg1, DWORD flags, FT_HANDLE* pHandle) { FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesReturned) { bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD), ftHandle, lpBuffer, dwBytesToRead, lpBytesReturned); - printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv); + if (dwBytesToRead != *lpBytesReturned) printf("\tW: AAAAAAAAAA size mismatch\n"); size_t nb = *lpBytesReturned; - if (nb < 0x100) { +#ifndef HIGHLEVEL + printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv); +#endif + if (nb < +#ifndef HIGHLEVEL + 0x100 +#else + 0x10 +#endif + ) { +#ifdef HIGHLEVEL + printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv); +#endif printf(" "); size_t i; for (i = 0; i < nb; ++i) { @@ -132,6 +151,9 @@ FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDW } if ((i & 15)) printf("\n"); } +#ifdef HIGHLEVEL + ftfake_cb(lpBuffer, nb); +#endif return rv; } @@ -161,13 +183,16 @@ FT_STATUS FT_SetUSBParameters(FT_HANDLE ftHandle, ULONG inxfersz, ULONG outxfers FT_STATUS FT_SetVIDPID(DWORD dwVid, DWORD dwPid) { bind(FT_STATUS, (DWORD, DWORD), dwVid, dwPid); +#ifndef HIGHLEVEL printf("FT_SetVIDPID(0x%04x, 0x%04x) = %d\n", dwVid, dwPid, rv); +#endif return rv; } FT_STATUS FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD len, LPDWORD written) { bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD), ftHandle, lpBuffer, len, written); printf("FT_Write(%p, %p, 0x%x, &0x%0x) = %d\n", ftHandle, lpBuffer, len, *written, rv); + if (*written != len) printf("\tW: AAAAAAAAAAAAAAAA size mismatch\n"); size_t nb = *written; if (nb < 0x100) { printf(" "); @@ -179,6 +204,11 @@ FT_STATUS FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD len, LPDWORD writt } if ((i & 15)) printf("\n"); } + +#ifdef HIGHLEVEL + ftfake_parsehl(lpBuffer, nb); +#endif + return rv; } diff --git a/libftfake_hl.h b/libftfake_hl.h new file mode 100644 index 0000000..b163cec --- /dev/null +++ b/libftfake_hl.h @@ -0,0 +1,220 @@ + +#ifndef LIBFTFAKE_HL_H_ +#define LIBFTFAKE_HL_H_ + +#include + +#define WARNSTR "\x1b[1;31mW:\x1b[0m " + +__attribute__((__packed__)) +struct settings { + uint8_t norm_or_pwIsMicrosec; + uint8_t clockfreq[2]; + uint8_t pw_trigscale[2]; + uint8_t ms1[3]; + uint8_t ms2[3]; + uint8_t ms3_ioflg[3]; + uint8_t unk00; + uint8_t ntrigsteps; + uint8_t unkf0; + uint8_t unk0f; + uint8_t capgenchans; + uint8_t voltage[2]; + uint8_t unk32; + uint8_t nabort; + uint8_t abort; +}; + +struct trigstep_nice { + bool ch_ignore[4]; + bool use_max_pw, use_min_pw; + bool ch_hiri1_lofa0[4]; + bool level1_edge0; + uint16_t pw_min, pw_max; + bool unkB2b3, unkB2b4, unkB3b6; // bit index: bytevalofsinglebit = 1< 0x20) { + gensize += len; + return; + } else { + printf("\tgenerate size: 0x%zx\n", gensize); + state_tonorm(); + } + } + + switch (buf[0]) { + case 0x93:printf("\t->application\n");break; + case 0x94:printf("\t->bootloader\n");break; + case 0xf0: + switch (buf[1]) { + case 0x00:printf("\tcapture reset\n");break; + case 0x01: + printf("\tstart capt/WFT\n"); + state = scwftres3; + break; + case 0x02:printf("\tsiggen start repeat\n");break; + case 0x03: + printf("\tmixed-mode sfc/wft\n"); + state=scwftres3; + break; + case 0x05: + printf("\tstart gendata dl\n"); + if (buf[2]!=0xf3)printf("\t" WARNSTR "unk arg2 0x%02x\n", buf[2]); + state = ingenupload; + gensize = 0; + break; + case 0x06: + printf("\tstart read\n"); + state = incapreadout; + capsize = 0; + break; + case 0x07:printf("\tsiggen start once\n");break; + default:printf("\t" WARNSTR "unk 0xf0 arg 0x%02x!\n", buf[1]); + } + break; + break; + case 0xf1: + if (len == 27) { + printf("\teep magic 0x%02x 0x%02x 0x%02x\n", + buf[1],buf[2],buf[3]); + } else if (len == 25) { + struct settings sett = *(struct settings*)&buf[1]; // hacks + bool weird = sett.unk00 != 0x00 || sett.unkf0 != 0xf0 || sett.unk0f != 0x0f + || sett.unk32 != 0x32 || sett.nabort != 0x01 || sett.abort != 0x00 + || (sett.capgenchans&0xf)!=0xf + || (sett.norm_or_pwIsMicrosec != 0x09 && sett.norm_or_pwIsMicrosec != 0x01); + uint8_t ioflg = sett.ms3_ioflg[2] & 0xf0; // MSB high nibble ORed with the inverse of nibble M at loc 0x12 + if (((uint8_t)ioflg ^ (uint8_t)(sett.capgenchans & 0xf0)) != 0xf0) + weird = true; + float freq = 100000.0f / *(uint16_t*)&sett.clockfreq[0]; + char normpw = '?'; + if (sett.norm_or_pwIsMicrosec == 0x09) normpw = 'P'; + if (sett.norm_or_pwIsMicrosec == 0x01) normpw = 'n'; + uint32_t ms1 = *(uint32_t*)&sett.ms1[0] & 0x00ffffff; + uint32_t ms2 = *(uint32_t*)&sett.ms2[0] & 0x00ffffff; + uint32_t ms3 = *(uint32_t*)&sett.ms3_ioflg[0] & 0x000fffff; + printf("\t%ssettings:\n", weird ? WARNSTR : ""); + printf("\t freq=%d kHz #tsteps=%hhu trigscale=0x%04x pwmicro=%c genmap=%c%c%c%c:%x(%x)\n", + (int)freq, sett.ntrigsteps, *(uint16_t*)&sett.pw_trigscale[0], normpw, + (sett.capgenchans & 0x10)?'1':'-', + (sett.capgenchans & 0x20)?'2':'-', + (sett.capgenchans & 0x40)?'3':'-', + (sett.capgenchans & 0x80)?'4':'-', + sett.capgenchans&0xf,ioflg>>4 + ); + printf("\t ms1=0x%06x ms2=0x%06x ms3=0x%06x\n", ms1, ms2, ms3); + float volt = 0.1f*roundf((sett.voltage[0] / 39.2f) * 10.0f); + printf("\t voltage=%.1f unk00=%x unkf0=%02x unk0f=%02x unk32=%02x nabort=%x abort=%x\n", + volt, sett.unk00, sett.unkf0, sett.unk0f, sett.unk32, sett.nabort, sett.abort); + } else { + printf("\t" WARNSTR "0xF1 formatting unknown!\n"); + } break; + case 0xf4: { + size_t nst = (len - 1) >> 2; + printf("\ttrigger: %zu steps\n", nst); + for (size_t i = 0; i < nst; ++i) { + size_t ind = 1 + i * 4; + + struct trigstep_nice step; + step.ch_ignore[0] = buf[ind+0] & 0x40; + step.ch_ignore[1] = buf[ind+0] & 0x80; + step.ch_ignore[2] = buf[ind+1] & 0x01; + step.ch_ignore[3] = buf[ind+1] & 0x02; + + step.use_max_pw = !(buf[ind+0] & 0x20); + step.use_min_pw = !(buf[ind+0] & 0x10); + + step.ch_hiri1_lofa0[0] = buf[ind+0] & 0x01; + step.ch_hiri1_lofa0[1] = buf[ind+0] & 0x02; + step.ch_hiri1_lofa0[2] = buf[ind+0] & 0x04; + step.ch_hiri1_lofa0[3] = buf[ind+0] & 0x08; + + step.pw_min = ((buf[ind+1] & 0xf8) >> 3) | ((uint16_t)(buf[ind+2] & 0x07) << 5); + step.pw_max = ((buf[ind+2] & 0xe0) >> 5) | ((uint16_t)(buf[ind+3] & 0x3f) << 3); + + step.level1_edge0 = buf[ind+3] & 0x80; + + step.unkB2b3 = buf[ind+2] & (1<<3); + step.unkB2b4 = buf[ind+2] & (1<<4); + step.unkB3b6 = buf[ind+3] & (1<<6); + + printf("\t"); + if (step.unkB2b3 || step.unkB2b4 || step.unkB3b6) printf(WARNSTR); + printf(" chans %c%c%c%c :: %s %s %s %s %s minpw=%d maxpw=%d", + (step.ch_ignore[0]?'-':'1'), + (step.ch_ignore[1]?'-':'2'), + (step.ch_ignore[2]?'-':'3'), + (step.ch_ignore[3]?'-':'4'), + + (step.ch_ignore[0]?"-":(step.ch_hiri1_lofa0[0]?"hiri":"lofa")), + (step.ch_ignore[1]?"-":(step.ch_hiri1_lofa0[1]?"hiri":"lofa")), + (step.ch_ignore[2]?"-":(step.ch_hiri1_lofa0[2]?"hiri":"lofa")), + (step.ch_ignore[3]?"-":(step.ch_hiri1_lofa0[3]?"hiri":"lofa")), + + step.level1_edge0 ? "level" : "edge", + step.use_min_pw ? (int)step.pw_min : (-1), + step.use_max_pw ? (int)step.pw_max : (-1) + ); + if (step.unkB2b3) printf(" uB2b3!"); + if (step.unkB2b4) printf(" uB2b4!"); + if (step.unkB3b6) printf(" uB3b6!"); + printf("\n"); + } + } break; + case 0xfd:printf("\techo status\n");break; + default: + printf("\t" WARNSTR "unknown command 0x%02x!\n", buf[0]); + break; + } +} + +static void ftfake_cb(void* buf_, size_t len) { + uint8_t* buf = (uint8_t*)buf_; + + switch (state) { + case incapreadout: + capsize += len; + break; + /*case ingenupload: + gensize += len; + break;*/ + case scwftres3: { + uint32_t trig_instant = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2]<<16); + printf("\ttrig_instant=0x%06x\n", trig_instant); + ++state; // to scfwres1 + } break; + case scwftres1: + printf("\t%sscwftres = 0x%02x\n", (buf[0] == 0xdd ? "" : WARNSTR), buf[0]); + state_tonorm(); + break; + default: break; + } +} + +#endif +