diff --git a/CHANGELOG.md b/CHANGELOG.md index 966d26729..fa2dd86fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman) - Chg adaptations for FPC communications (work in progress) (@iceman) - Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato) - Fix 'LEGIC SIM' - remake of legic sim (@drandreas) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9cb3758af..f3b2e6c60 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -392,7 +392,8 @@ void SendStatus(void) { I2C_print_status(); #endif #ifdef WITH_LF - printConfig(); //LF Sampling config + printConfig(); // LF Sampling config + printT55xxConfig(); // LF T55XX Config #endif printUSBSpeed(); Dbprintf("Various"); @@ -625,6 +626,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { switch(c->cmd) { #ifdef WITH_LF + case CMD_SET_LF_T55XX_CONFIG: + setT55xxConfig((t55xx_config *) c->d.asBytes); + break; case CMD_SET_LF_SAMPLING_CONFIG: setSamplingConfig((sample_config *) c->d.asBytes); break; @@ -701,10 +705,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] ); break; - case CMD_T55XX_READ_BLOCK: + case CMD_T55XX_READ_BLOCK: { T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); break; - case CMD_T55XX_WRITE_BLOCK: + } + case CMD_T55XX_WRITE_BLOCK: T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); break; case CMD_T55XX_WAKEUP: @@ -1475,6 +1480,10 @@ void __attribute__((noreturn)) AppMain(void) { usart_init(); #endif +#ifdef WITH_FLASH + loadT55xxConfig(); +#endif + // This is made as late as possible to ensure enumeration without timeout // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 usb_disable(); diff --git a/armsrc/apps.h b/armsrc/apps.h index f8d24f4ae..81a073904 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -108,6 +108,10 @@ void TurnReadLFOn(uint32_t delay); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd); void Cotag(uint32_t arg0); +void setT55xxConfig(t55xx_config *c); +t55xx_config * getT55xxConfig(void); +void printT55xxConfig(void); +void loadT55xxConfig(void); /// iso14443b.h void SimulateIso14443bTag(uint32_t pupi); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index a8642dd74..d7ec37f81 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,7 +1,5 @@ #include "flashmem.h" - - /* here: use NCPS2 @ PA10: */ #define SPI_CSR_NUM 2 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 612e2a2f4..df49da530 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -18,6 +18,8 @@ #include "lfsampling.h" #include "protocols.h" #include "usb_cdc.h" // for usb_poll_validate_length +#include "common.h" +#include "flashmem.h" // persistence on mem #ifndef SHORT_COIL # define SHORT_COIL() LOW(GPIO_SSC_DOUT) @@ -26,11 +28,11 @@ # define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #endif -#define START_GAP 28*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) -#define WRITE_GAP 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) -#define WRITE_0 15*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) -#define WRITE_1 47*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 -#define READ_GAP 15*8 +//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) +//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) +//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) +//#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 +//#define READ_GAP 15*8 // VALUES TAKEN FROM EM4x function: SendForward // START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) @@ -49,7 +51,68 @@ // new timer: // = 1us = 1.5ticks // 1fc = 8us = 12ticks +/* +Default LF T55xx config is set to: + startgap = 31*8 + writegap = 17*8 + write_0 = 15*8 + write_1 = 47*8 + read_gap = 15*8 +*/ +t55xx_config t_config = { 31*8, 17*8, 15*8, 47*8, 15*8 } ; +void printT55xxConfig(void) { + Dbprintf("LF T55XX config"); + Dbprintf(" [q] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); + Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap); + Dbprintf(" [d] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); + Dbprintf(" [a] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); + Dbprintf(" [t] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); +} +void setT55xxConfig(t55xx_config *c) { + + if (c->start_gap != 0) t_config.start_gap = c->start_gap*8; + if (c->write_gap != 0) t_config.write_gap = c->write_gap*8; + if (c->write_0 != 0) t_config.write_0 = c->write_0*8; + if (c->write_1 != 0) t_config.write_1 = c->write_1*8; + if (c->read_gap != 0) t_config.read_gap = c->read_gap*8; + + printT55xxConfig(); + +#if WITH_FLASH + if (!FlashInit()) + return; + + Flash_CheckBusy(BUSY_TIMEOUT); + + uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, sizeof(t55xx_config)); + FlashStop(); + + if ( isok == T55XX_CONFIG_LEN) { + if (MF_DBGLEVEL > 1) DbpString("T55XX Config save success"); + } +#endif +} + +t55xx_config* getT55xxConfig(void) { + return &t_config; +} + +void loadT55xxConfig(void) { +#if WITH_FLASH + if (!FlashInit()) + return; + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN); + FlashStop(); + + if ( isok == T55XX_CONFIG_LEN) { + if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); + } +#endif +} /** * Function to do a modulation and then get samples. @@ -1266,11 +1329,11 @@ void TurnReadLF_off(uint32_t delay) { // Write one bit to card void T55xxWriteBit(int bit) { if (!bit) - TurnReadLFOn(WRITE_0); + TurnReadLFOn(t_config.write_0); else - TurnReadLFOn(WRITE_1); + TurnReadLFOn(t_config.write_1); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(WRITE_GAP); + WaitUS(t_config.write_gap); } // Send T5577 reset command then read stream (see if we can identify the start of the stream) @@ -1284,17 +1347,17 @@ void T55xxResetRead(void) { // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // reset tag - op code 00 T55xxWriteBit(0); T55xxWriteBit(0); - TurnReadLFOn(READ_GAP); + TurnReadLFOn(t_config.read_gap); // Acquisition DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); @@ -1319,10 +1382,10 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); if (testMode) Dbprintf("TestMODE"); // Std Opcode 10 @@ -1404,10 +1467,10 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // Opcode 1[page] T55xxWriteBit(1); @@ -1450,11 +1513,11 @@ void T55xxWakeUp(uint32_t Pwd){ // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // Opcode 10 T55xxWriteBit(1); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9102efc5c..a1f072425 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -187,6 +187,22 @@ int usage_t55xx_recoverpw(){ PrintAndLogEx(NORMAL, " lf t55xx wipe Q5 - wipes a t5555 Q5 tag, config block 0x6001F004"); return 0; } +int usage_lf_deviceconfig(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " a <8..28> - Set start gap"); + PrintAndLogEx(NORMAL, " b <8..28> - Set write gap"); + PrintAndLogEx(NORMAL, " c <8..28> - Set write ZERO gap"); + PrintAndLogEx(NORMAL, " d <8..28> - Set write ONE gap"); + PrintAndLogEx(NORMAL, " e <8..28> - Set read gap"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 b 20 - start gap 31*8, write gap 20*8"); + PrintAndLogEx(NORMAL, ""); + return 0; +} static int CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ @@ -461,8 +477,7 @@ static int SanityOfflineCheck( bool useGraphBuffer ){ int CmdT55xxDetect(const char *Cmd){ bool errors = false; - bool useGB = false; - bool usepwd = false; + bool useGB = false, usepwd = false; uint32_t password = 0; uint8_t cmdp = 0; @@ -1291,7 +1306,7 @@ int CmdT55xxDump(const char *Cmd){ return 1; } -bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ +bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) { // arg0 bitmodes: // bit0 = pwdmode // bit1 = page to read from @@ -1882,11 +1897,60 @@ int CmdT55xxDetectPage1(const char *Cmd){ return success; } +int CmdT55xxSetDeviceConfig(const char *Cmd){ + uint8_t startgap = 0, writegap = 0; + uint8_t write0 = 0, write1 = 0, readgap = 0; + bool errors = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_deviceconfig(); + case 'a': + errors |= param_getdec(Cmd, cmdp+1, &startgap); + cmdp += 2; + break; + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &writegap); + cmdp += 2; + break; + case 'c': + errors |= param_getdec(Cmd, cmdp+1, &write0); + cmdp += 2; + break; + case 'd': + errors |= param_getdec(Cmd, cmdp+1, &write1); + cmdp += 2; + break; + case 'e': + errors |= param_getdec(Cmd, cmdp+1, &readgap); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + } + + //Validations + if (errors || cmdp == 0) return usage_lf_deviceconfig(); + + t55xx_config config = { startgap, writegap, write0, write1, readgap }; + + UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {0,0,0} }; + memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index b6c355778..15adab0b6 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -160,6 +160,7 @@ extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); +bool AquireDataEx( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing ) ; bool detectPassword(int password); diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 2ced2cd18..59027c9d3 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -105,6 +105,7 @@ typedef struct { #define CMD_VIKING_CLONE_TAG 0x0222 #define CMD_T55XX_WAKEUP 0x0224 #define CMD_COTAG 0x0225 +#define CMD_SET_LF_T55XX_CONFIG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/include/common.h b/include/common.h index 8a3f33abd..24e085699 100644 --- a/include/common.h +++ b/include/common.h @@ -55,7 +55,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #endif #ifndef FLASH_MEM_MAX_SIZE -# define FLASH_MEM_MAX_SIZE 0x3FFFF +# define FLASH_MEM_MAX_SIZE 0x3FFFF // (262143) #endif #ifndef FLASH_MEM_ID_LEN @@ -70,6 +70,15 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; # define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN) #endif +#if WITH_FLASH +#ifndef T55XX_CONFIG_LEN +# define T55XX_CONFIG_LEN sizeof( t55xx_config ) +#endif + +#ifndef T55XX_CONFIG_OFFSET +#define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN - T55XX_CONFIG_LEN) +#endif +#endif // RDV40, validation structure to help identifying that client/firmware is talking with RDV40 typedef struct { diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 51df5896b..d6b240fb6 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -43,6 +43,14 @@ typedef struct{ int trigger_threshold; } sample_config; +typedef struct{ + uint16_t start_gap; + uint16_t write_gap; + uint16_t write_0; + uint16_t write_1; + uint16_t read_gap; +} t55xx_config; + // For the bootloader #define CMD_DEVICE_INFO 0x0000 #define CMD_SETUP_WRITE 0x0001 @@ -130,6 +138,7 @@ typedef struct{ #define CMD_VIKING_CLONE_TAG 0x0222 #define CMD_T55XX_WAKEUP 0x0224 #define CMD_COTAG 0x0225 +#define CMD_SET_LF_T55XX_CONFIG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */