From cb366e9dbd0f421c143d6a9f02d7e0abc86c90ba Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 22 Jan 2015 23:01:29 +0100 Subject: [PATCH 01/11] Added a lf acquisition-mode which can do decimation and quantization, in order to be able to record longer transactions --- armsrc/lfops.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index f5040850c..1d7d2036e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -8,6 +8,7 @@ // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- +#include #include "proxmark3.h" #include "apps.h" #include "util.h" @@ -16,6 +17,83 @@ #include "string.h" #include "lfdemod.h" +typedef struct { + uint8_t * buffer; + uint32_t numbits; + uint8_t position; +} BitstreamOut; +/** + * @brief Pushes bit onto the stream + * @param stream + * @param bit + */ +void pushBit( BitstreamOut* stream, bool bit) +{ + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = stream->position & 7; + *(stream->buffer+bytepos) |= (bit & 1) << (7 - bitpos); + stream->position++; + stream->numbits++; +} +void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool averaging) +{ + //A decimation of 2 means we keep every 2nd sample + //A decimation of 3 means we keep 1 in 3 samples. + //A quantization of 1 means one bit is discarded from the sample (division by 2). + uint8_t *dest = (uint8_t *)BigBuf; + int bufsize = BIGBUF_SIZE; + memset(dest, 0, bufsize); + // You can't decimate 8 bits more than 7 times + if(quantization > 7) quantization = 7; + // Use a bit stream to handle the output + BitstreamOut data = { dest , 0, 0}; + int sample_counter = 0; + uint8_t sample = 0; + //If we want to do averaging + uint32_t sample_sum =0 ; + uint32_t sample_total_numbers =0 ; + uint32_t sample_total_saved =0 ; + + for(;;) { + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + sample_total_numbers++; + if (trigger_threshold != -1 && sample < trigger_threshold) + continue; + + LED_D_OFF(); + trigger_threshold = -1; + sample_counter++; + sample_sum += sample; + //Check decimation + if(sample_counter < decimation) continue; + //Averaging + if(averaging) sample = sample_sum / decimation; + + sample_counter = 0; + sample_sum =0; + sample_total_saved ++; + pushBit(&data, sample & 0x80); + if(quantization < 7) pushBit(&data, sample & 0x40); + if(quantization < 6) pushBit(&data, sample & 0x20); + if(quantization < 5) pushBit(&data, sample & 0x10); + if(quantization < 4) pushBit(&data, sample & 0x08); + if(quantization < 3) pushBit(&data, sample & 0x04); + if(quantization < 2) pushBit(&data, sample & 0x02); + if(quantization < 1) pushBit(&data, sample & 0x01); + + if(data.numbits +1 >= bufsize) break; + } + } + Dbprintf("Done, saved %l out of %l seen samples.",sample_total_saved, sample_total_numbers); + +} + /** * Does the sample acquisition. If threshold is specified, the actual sampling From 7242efa07c18a92c4139c26ad7009f2d8866fc89 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 22 Jan 2015 23:04:59 +0100 Subject: [PATCH 02/11] bugfix --- armsrc/lfops.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 1d7d2036e..c1bf6d2b0 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -8,7 +8,6 @@ // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- -#include #include "proxmark3.h" #include "apps.h" #include "util.h" @@ -62,9 +61,9 @@ void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - sample_total_numbers++; if (trigger_threshold != -1 && sample < trigger_threshold) continue; + sample_total_numbers++; LED_D_OFF(); trigger_threshold = -1; @@ -87,7 +86,7 @@ void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool if(quantization < 2) pushBit(&data, sample & 0x02); if(quantization < 1) pushBit(&data, sample & 0x01); - if(data.numbits +1 >= bufsize) break; + if((data.numbits / 8) +1 >= bufsize) break; } } Dbprintf("Done, saved %l out of %l seen samples.",sample_total_saved, sample_total_numbers); From 7c676e7269ce6ca6be9fbadb237873dd31b4d27d Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 26 Jan 2015 21:15:28 +0100 Subject: [PATCH 03/11] Some documentation --- armsrc/lfops.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c1bf6d2b0..3cd2bc36d 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -34,7 +34,19 @@ void pushBit( BitstreamOut* stream, bool bit) stream->position++; stream->numbits++; } -void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool averaging) +/** + * @brief Does LF sample acquisition, this method implements decimation and quantization in order to + * be able to provide longer sample traces. + * @param decimation - how much should the signal be decimated. A decimation of 1 means every sample, 2 means + * every other sample, etc. + * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample. + * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set + * to -1 to ignore threshold. + * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample + * value that will be used is the average value of the three samples. + * @return the number of bits occupied by the samples. + */ +uint8_t DoAcquisition(int decimation, int bits_per_sample, int trigger_threshold, bool averaging) { //A decimation of 2 means we keep every 2nd sample //A decimation of 3 means we keep 1 in 3 samples. @@ -42,8 +54,9 @@ void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool uint8_t *dest = (uint8_t *)BigBuf; int bufsize = BIGBUF_SIZE; memset(dest, 0, bufsize); - // You can't decimate 8 bits more than 7 times - if(quantization > 7) quantization = 7; + if(bits_per_sample < 1) bits_per_sample = 1; + if(bits_per_sample > 8) bits_per_sample = 8; + // Use a bit stream to handle the output BitstreamOut data = { dest , 0, 0}; int sample_counter = 0; @@ -78,19 +91,20 @@ void DoAcquisition(int decimation, int quantization, int trigger_threshold, bool sample_sum =0; sample_total_saved ++; pushBit(&data, sample & 0x80); - if(quantization < 7) pushBit(&data, sample & 0x40); - if(quantization < 6) pushBit(&data, sample & 0x20); - if(quantization < 5) pushBit(&data, sample & 0x10); - if(quantization < 4) pushBit(&data, sample & 0x08); - if(quantization < 3) pushBit(&data, sample & 0x04); - if(quantization < 2) pushBit(&data, sample & 0x02); - if(quantization < 1) pushBit(&data, sample & 0x01); + if(bits_per_sample > 1) pushBit(&data, sample & 0x40); + if(bits_per_sample > 2) pushBit(&data, sample & 0x20); + if(bits_per_sample > 3) pushBit(&data, sample & 0x10); + if(bits_per_sample > 4) pushBit(&data, sample & 0x08); + if(bits_per_sample > 5) pushBit(&data, sample & 0x04); + if(bits_per_sample > 6) pushBit(&data, sample & 0x02); + if(bits_per_sample > 7) pushBit(&data, sample & 0x01); - if((data.numbits / 8) +1 >= bufsize) break; + if((data.numbits >> 3) +1 >= bufsize) break; } } Dbprintf("Done, saved %l out of %l seen samples.",sample_total_saved, sample_total_numbers); + return data.numbits; } From f6d9fb173fec6d117faeb6c39cf37ee449d4ef16 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 29 Jan 2015 00:57:22 +0100 Subject: [PATCH 04/11] Added client-side support for recording longer samples, fixed last (?) issues on device-side --- armsrc/appmain.c | 4 +- armsrc/apps.h | 7 +- armsrc/lfops.c | 164 +++++++++++++++++++++++++---------------------- client/cmddata.c | 61 +++++++++++++++--- client/cmdlf.c | 97 +++++++++++++++++++++++----- client/graph.h | 3 +- client/util.c | 28 ++++++++ client/util.h | 2 + 8 files changed, 260 insertions(+), 106 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 530dc39cd..83d9dd1fb 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -630,7 +630,7 @@ void UsbPacketReceived(uint8_t *packet, int len) switch(c->cmd) { #ifdef WITH_LF case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: - AcquireRawAdcSamples125k(c->arg[0]); + AcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2]); cmd_send(CMD_ACK,0,0,0,0,0); break; case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: @@ -910,7 +910,7 @@ void UsbPacketReceived(uint8_t *packet, int len) cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,0,((byte_t*)BigBuf)+c->arg[0]+i,len); } // Trigger a finish downloading signal with an ACK frame - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,bits_per_sample,decimation,0,0,0); LED_B_OFF(); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 5a1ab6902..110e03b3a 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -81,7 +81,6 @@ int AvgAdc(int ch); void ToSendStuffBit(int b); void ToSendReset(void); void ListenReaderField(int limit); -void AcquireRawAdcSamples125k(int at134khz); void SnoopLFRawAdcSamples(int divisor, int trigger_threshold); void DoAcquisition125k(int trigger_threshold); extern int ToSendMax; @@ -144,7 +143,11 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_HF_ISO14443A_READER_MOD (4<<0) /// lfops.h -void AcquireRawAdcSamples125k(int divisor); +extern uint8_t decimation; +extern uint8_t bits_per_sample ; +extern bool averaging; + +void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2); void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 3cd2bc36d..c10314473 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -16,47 +16,58 @@ #include "string.h" #include "lfdemod.h" +uint8_t decimation = 1; +uint8_t bits_per_sample = 8; +bool averaging = 1; + + typedef struct { uint8_t * buffer; uint32_t numbits; - uint8_t position; + uint32_t position; } BitstreamOut; /** * @brief Pushes bit onto the stream * @param stream * @param bit */ -void pushBit( BitstreamOut* stream, bool bit) +void pushBit( BitstreamOut* stream, uint8_t bit) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = stream->position & 7; - *(stream->buffer+bytepos) |= (bit & 1) << (7 - bitpos); + *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); stream->position++; stream->numbits++; } + /** - * @brief Does LF sample acquisition, this method implements decimation and quantization in order to + * Does the sample acquisition. If threshold is specified, the actual sampling + * is not commenced until the threshold has been reached. + * This method implements decimation and quantization in order to * be able to provide longer sample traces. - * @param decimation - how much should the signal be decimated. A decimation of 1 means every sample, 2 means - * every other sample, etc. - * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample. + * Uses the following global settings: + * - decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc. + * - bits_per_sample - bits per sample. Max 8, min 1 bit per sample. + * - averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample + * value that will be used is the average value of the three samples. + * * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set * to -1 to ignore threshold. - * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample - * value that will be used is the average value of the three samples. + * @param silent - is true, now outputs are made. If false, dbprints the status * @return the number of bits occupied by the samples. */ -uint8_t DoAcquisition(int decimation, int bits_per_sample, int trigger_threshold, bool averaging) +uint32_t DoAcquisition125k_internal(int trigger_threshold,bool silent) { - //A decimation of 2 means we keep every 2nd sample - //A decimation of 3 means we keep 1 in 3 samples. - //A quantization of 1 means one bit is discarded from the sample (division by 2). + //. uint8_t *dest = (uint8_t *)BigBuf; int bufsize = BIGBUF_SIZE; memset(dest, 0, bufsize); + if(bits_per_sample < 1) bits_per_sample = 1; if(bits_per_sample > 8) bits_per_sample = 8; + if(decimation < 1) decimation = 1; + // Use a bit stream to handle the output BitstreamOut data = { dest , 0, 0}; int sample_counter = 0; @@ -66,7 +77,7 @@ uint8_t DoAcquisition(int decimation, int bits_per_sample, int trigger_threshold uint32_t sample_total_numbers =0 ; uint32_t sample_total_saved =0 ; - for(;;) { + while(!BUTTON_PRESS()) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; @@ -74,76 +85,59 @@ uint8_t DoAcquisition(int decimation, int bits_per_sample, int trigger_threshold } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); if (trigger_threshold != -1 && sample < trigger_threshold) continue; + + trigger_threshold = -1; sample_total_numbers++; - LED_D_OFF(); - trigger_threshold = -1; - sample_counter++; - sample_sum += sample; + if(averaging) + { + sample_sum += sample; + } //Check decimation - if(sample_counter < decimation) continue; + if(decimation > 1) + { + sample_counter++; + if(sample_counter < decimation) continue; + sample_counter = 0; + } //Averaging - if(averaging) sample = sample_sum / decimation; - - sample_counter = 0; - sample_sum =0; + if(averaging && decimation > 1) { + sample = sample_sum / decimation; + sample_sum =0; + } + //Store the sample sample_total_saved ++; - pushBit(&data, sample & 0x80); - if(bits_per_sample > 1) pushBit(&data, sample & 0x40); - if(bits_per_sample > 2) pushBit(&data, sample & 0x20); - if(bits_per_sample > 3) pushBit(&data, sample & 0x10); - if(bits_per_sample > 4) pushBit(&data, sample & 0x08); - if(bits_per_sample > 5) pushBit(&data, sample & 0x04); - if(bits_per_sample > 6) pushBit(&data, sample & 0x02); - if(bits_per_sample > 7) pushBit(&data, sample & 0x01); - - if((data.numbits >> 3) +1 >= bufsize) break; + if(bits_per_sample == 8){ + dest[sample_total_saved-1] = sample; + data.numbits = sample_total_saved << 3;//Get the return value correct + if(sample_total_saved >= bufsize) break; + } + else{ + pushBit(&data, sample & 0x80); + if(bits_per_sample > 1) pushBit(&data, sample & 0x40); + if(bits_per_sample > 2) pushBit(&data, sample & 0x20); + if(bits_per_sample > 3) pushBit(&data, sample & 0x10); + if(bits_per_sample > 4) pushBit(&data, sample & 0x08); + if(bits_per_sample > 5) pushBit(&data, sample & 0x04); + if(bits_per_sample > 6) pushBit(&data, sample & 0x02); + //Not needed, 8bps is covered above + //if(bits_per_sample > 7) pushBit(&data, sample & 0x01); + if((data.numbits >> 3) +1 >= bufsize) break; + } } } - Dbprintf("Done, saved %l out of %l seen samples.",sample_total_saved, sample_total_numbers); + if(!silent) + { + Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample); + Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", + dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + } return data.numbits; } - - -/** -* Does the sample acquisition. If threshold is specified, the actual sampling -* is not commenced until the threshold has been reached. -* @param trigger_threshold - the threshold -* @param silent - is true, now outputs are made. If false, dbprints the status -*/ -void DoAcquisition125k_internal(int trigger_threshold,bool silent) -{ - uint8_t *dest = (uint8_t *)BigBuf; - int n = sizeof(BigBuf); - int i; - - memset(dest, 0, n); - i = 0; - for(;;) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - LED_D_OFF(); - if (trigger_threshold != -1 && dest[i] < trigger_threshold) - continue; - else - trigger_threshold = -1; - if (++i >= n) break; - } - } - if(!silent) - { - Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); - - } -} /** * Perform sample aquisition. */ @@ -181,11 +175,27 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) /** * Initializes the FPGA, and acquires the samples. **/ -void AcquireRawAdcSamples125k(int divisor) +void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2) { - LFSetupFPGAForADC(divisor, true); - // Now call the acquisition routine - DoAcquisition125k_internal(-1,false); + if (arg1 != 0) + { + averaging = (arg1 & 0x80) != 0; + bits_per_sample = (arg1 & 0x0F); + } + if(arg2 != 0) + { + decimation = arg2; + } + + Dbprintf("Sampling config: "); + Dbprintf(" divisor: %d ", divisor); + Dbprintf(" bps: %d ", bits_per_sample); + Dbprintf(" decimation: %d ", decimation); + Dbprintf(" averaging: %d ", averaging); + + LFSetupFPGAForADC(divisor, true); + // Now call the acquisition routine + DoAcquisition125k_internal(-1,false); } /** * Initializes the FPGA for snoop-mode, and acquires the samples. @@ -1479,7 +1489,7 @@ int DemodPCF7931(uint8_t **outBlocks) { int lmin=128, lmax=128; uint8_t dir; - AcquireRawAdcSamples125k(0); + AcquireRawAdcSamples125k(0,0,0); lmin = 64; lmax = 192; diff --git a/client/cmddata.c b/client/cmddata.c index a88fa4e10..793845807 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1051,6 +1051,29 @@ int CmdHpf(const char *Cmd) RepaintGraphWindow(); return 0; } +typedef struct { + uint8_t * buffer; + uint32_t numbits; + uint32_t position; +}BitstreamOut; + +bool _headBit( BitstreamOut *stream) +{ + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = (stream->position++) & 7; // mask out 00000111 + return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; +} + +uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) +{ + int i; + uint8_t val = 0; + for(i =0 ; i < bits_per_sample; i++) + { + val |= (_headBit(b) << (7-i)); + } + return val; +} int CmdSamples(const char *Cmd) { @@ -1063,15 +1086,35 @@ int CmdSamples(const char *Cmd) if (n > sizeof(got)) n = sizeof(got); - PrintAndLog("Reading %d samples from device memory\n", n); - GetFromBigBuf(got,n,0); - WaitForResponse(CMD_ACK,NULL); - for (int j = 0; j < n; j++) { - GraphBuffer[j] = ((int)got[j]) - 128; - } - GraphTraceLen = n; - RepaintGraphWindow(); - return 0; + PrintAndLog("Reading %d bytes from device memory\n", n); + GetFromBigBuf(got,n,0); + PrintAndLog("Data fetched"); + UsbCommand response; + WaitForResponse(CMD_ACK, &response); + uint8_t bits_per_sample = response.arg[0]; + PrintAndLog("Samples packed at %d bits per sample", bits_per_sample); + if(bits_per_sample < 8) + { + PrintAndLog("Unpacking..."); + BitstreamOut bout = { got, bits_per_sample * n, 0}; + int j =0; + for (j = 0; j * bits_per_sample < n * 8 && j < GraphTraceLen; j++) { + uint8_t sample = getByte(bits_per_sample, &bout); + GraphBuffer[j] = ((int) sample )- 128; + } + GraphTraceLen = j; + PrintAndLog("Unpacked %d samples" , j ); + }else + { + for (int j = 0; j < n; j++) { + GraphBuffer[j] = ((int)got[j]) - 128; + } + GraphTraceLen = n; + + } + + RepaintGraphWindow(); + return 0; } int CmdTuneSamples(const char *Cmd) diff --git a/client/cmdlf.c b/client/cmdlf.c index e3361cb50..93a9f5866 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -356,24 +356,91 @@ int CmdIndalaClone(const char *Cmd) return 0; } +int CmdLFReadUsage() +{ + PrintAndLog("Usage: lf read [H|] [b ] [d ] [a 0|1]"); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" H High frequency (134 KHz). Defaults to 125 KHz"); + PrintAndLog(" Manually set divisor. 88-> 134KHz, 95-> 125 Hz"); + PrintAndLog(" b Sets resolution of bits per sample. Default (max): 8"); + PrintAndLog(" d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); + PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1"); + PrintAndLog("Examples:"); + PrintAndLog(" lf read"); + PrintAndLog(" Samples at 125KHz, 8bps."); + PrintAndLog(" lf read h b 4 d 3"); + PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with "); + PrintAndLog(" a resolution of 4 bits per sample."); + return 0; +} int CmdLFRead(const char *Cmd) { - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; + uint8_t divisor = 95;//Frequency divisor + uint8_t bps = 8; // Bits per sample + uint8_t decimation = 1; //How many to keep + bool averaging = 1; // Should we use averaging when discarding samples? + bool errors = FALSE; - // 'h' means higher-low-frequency, 134 kHz - if(*Cmd == 'h') { - c.arg[0] = 1; - } else if (*Cmd == '\0') { - c.arg[0] = 0; - } else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) { - PrintAndLog("Samples 1: 'lf read'"); - PrintAndLog(" 2: 'lf read h'"); - PrintAndLog(" 3: 'lf read '"); - return 0; - } - SendCommand(&c); - WaitForResponse(CMD_ACK,NULL); - return 0; + uint8_t cmdp =0; + if(param_getchar(Cmd, cmdp) == 'h') + { + return CmdLFReadUsage(); + } + + // Divisor + if(param_getchar(Cmd, cmdp) == 'H') { + divisor = 88; + cmdp++; + }else if(param_isdec(Cmd,cmdp) ) + { + errors |= param_getdec(Cmd,cmdp, &divisor); + } + //BPS + if(param_getchar(Cmd, cmdp) == 'b') { + errors |= param_getdec(Cmd,cmdp+1,&bps); + cmdp+=2; + } + //Decimation + if(param_getchar(Cmd, cmdp) == 'd') + { + errors |= param_getdec(Cmd,cmdp+1,&decimation); + cmdp+=2; + } + //Averaging + if(param_getchar(Cmd, cmdp) == 'a') + { + averaging = param_getchar(Cmd,cmdp+1) == '1'; + cmdp+=2; + } + //Validations + if(errors) + { + return CmdLFReadUsage(); + } + + //Bps is limited to 8, so fits in lower half of arg1 + if(bps > 8) bps = 8; + + //Feedback + PrintAndLog("Sampling config: "); + PrintAndLog(" divisor: %d ", divisor); + PrintAndLog(" bps: %d ", bps); + PrintAndLog(" decimation: %d ", decimation); + PrintAndLog(" averaging: %d ", averaging); + PrintAndLog("OBS, this is sticky on the device and affects all LF listening operations"); + PrintAndLog("To reset, issue 'lf read'"); + + //And ship it to device + //Averaging is a flag on high-bit of arg[1] + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; + c.arg[0] = divisor; + c.arg[1] = bps | (averaging << 7) ; + c.arg[2] = decimation; + + SendCommand(&c); + WaitForResponse(CMD_ACK,NULL); + return 0; } static void ChkBitstream(const char *str) diff --git a/client/graph.h b/client/graph.h index 1abeeb25a..2c448161c 100644 --- a/client/graph.h +++ b/client/graph.h @@ -20,7 +20,8 @@ int GetClock(const char *str, int peak, int verbose); int GetNRZpskClock(const char *str, int peak, int verbose); void setGraphBuf(uint8_t *buff, size_t size); -#define MAX_GRAPH_TRACE_LEN (1024*128) +// Max graph trace len: 40000 (bigbuf) * 8 (at 1 bit per sample) +#define MAX_GRAPH_TRACE_LEN (40000 * 8 ) extern int GraphBuffer[MAX_GRAPH_TRACE_LEN]; extern int GraphTraceLen; diff --git a/client/util.c b/client/util.c index b8d5c316c..bce1c122e 100644 --- a/client/util.c +++ b/client/util.c @@ -227,6 +227,34 @@ uint8_t param_get8(const char *line, int paramnum) return param_get8ex(line, paramnum, 10, 0); } +/** + * @brief Reads a decimal integer + * @param line + * @param paramnum + * @return + */ +uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination) +{ + uint8_t val = param_get8ex(line, paramnum, 10, 10); + (*destination) = val; + return 0; +} +/** + * @brief Checks if param is decimal + * @param line + * @param paramnum + * @return + */ +uint8_t param_isdec(const char *line, int paramnum) +{ + int bg, en; + //TODO, check more thorougly + if (!param_getptr(line, &bg, &en, paramnum)) return 1; + // return strtoul(&line[bg], NULL, 10) & 0xff; + + return 0; +} + uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base) { int bg, en; diff --git a/client/util.h b/client/util.h index 22d41e0c8..5001acdcb 100644 --- a/client/util.h +++ b/client/util.h @@ -49,6 +49,8 @@ uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base); +uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination); +uint8_t param_isdec(const char *line, int paramnum); int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt); int param_getstr(const char *line, int paramnum, char * str); From 31abe49fd323411b391dd10335eb4c60cfcecb06 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 30 Jan 2015 23:03:44 +0100 Subject: [PATCH 05/11] Some more fixes to longer lf recordings. Now also supports longer snoops, and an additional command 'lf config' has been defined, instead of having to specify all params for every call --- armsrc/Makefile | 2 +- armsrc/appmain.c | 14 +-- armsrc/apps.h | 4 +- armsrc/lfops.c | 241 +++++------------------------------------- armsrc/lfsampling.c | 251 ++++++++++++++++++++++++++++++++++++++++++++ armsrc/lfsampling.h | 59 +++++++++++ client/cmddata.c | 25 +++-- client/cmdlf.c | 225 +++++++++++++++++++++++---------------- client/util.c | 9 +- include/usb_cmd.h | 11 ++ 10 files changed, 518 insertions(+), 323 deletions(-) create mode 100644 armsrc/lfsampling.c create mode 100644 armsrc/lfsampling.h diff --git a/armsrc/Makefile b/armsrc/Makefile index b9019541e..4e460623f 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -14,7 +14,7 @@ APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ #-DWITH_LCD #SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2.c +SRC_LF = lfops.c hitag2.c lfsampling.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443.c diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 83d9dd1fb..32b7e5924 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -23,7 +23,7 @@ #include "legicrf.h" #include - +#include "lfsampling.h" #ifdef WITH_LCD #include "LCD.h" #endif @@ -629,16 +629,17 @@ void UsbPacketReceived(uint8_t *packet, int len) switch(c->cmd) { #ifdef WITH_LF + case CMD_SET_LF_SAMPLING_CONFIG: + setSamplingConfig((sample_config *) c->d.asBytes); + break; case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: - AcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2]); - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,SampleLF(),0,0,0,0); break; case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); break; case CMD_LF_SNOOP_RAW_ADC_SAMPLES: - SnoopLFRawAdcSamples(c->arg[0], c->arg[1]); - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,SnoopLF(),0,0,0,0); break; case CMD_HID_DEMOD_FSK: CmdHIDdemodFSK(c->arg[0], 0, 0, 1); @@ -910,7 +911,8 @@ void UsbPacketReceived(uint8_t *packet, int len) cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,0,((byte_t*)BigBuf)+c->arg[0]+i,len); } // Trigger a finish downloading signal with an ACK frame - cmd_send(CMD_ACK,bits_per_sample,decimation,0,0,0); + // We put a 1 in arg[0] to alert the host we're also sending sample_config + cmd_send(CMD_ACK,1,0,0,getSamplingConfig(),sizeof(sample_config)); LED_B_OFF(); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 110e03b3a..89440bfec 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -81,8 +81,6 @@ int AvgAdc(int ch); void ToSendStuffBit(int b); void ToSendReset(void); void ListenReaderField(int limit); -void SnoopLFRawAdcSamples(int divisor, int trigger_threshold); -void DoAcquisition125k(int trigger_threshold); extern int ToSendMax; extern uint8_t ToSend[]; extern uint32_t BigBuf[]; @@ -147,7 +145,7 @@ extern uint8_t decimation; extern uint8_t bits_per_sample ; extern bool averaging; -void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2); +void AcquireRawAdcSamples125k(int divisor); void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c10314473..43af4eed4 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -15,231 +15,44 @@ #include "crc16.h" #include "string.h" #include "lfdemod.h" - -uint8_t decimation = 1; -uint8_t bits_per_sample = 8; -bool averaging = 1; +#include "lfsampling.h" -typedef struct { - uint8_t * buffer; - uint32_t numbits; - uint32_t position; -} BitstreamOut; /** - * @brief Pushes bit onto the stream - * @param stream - * @param bit + * Function to do a modulation and then get samples. + * @param delay_off + * @param period_0 + * @param period_1 + * @param command */ -void pushBit( BitstreamOut* stream, uint8_t bit) -{ - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = stream->position & 7; - *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); - stream->position++; - stream->numbits++; -} - -/** - * Does the sample acquisition. If threshold is specified, the actual sampling - * is not commenced until the threshold has been reached. - * This method implements decimation and quantization in order to - * be able to provide longer sample traces. - * Uses the following global settings: - * - decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc. - * - bits_per_sample - bits per sample. Max 8, min 1 bit per sample. - * - averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample - * value that will be used is the average value of the three samples. - * - * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set - * to -1 to ignore threshold. - * @param silent - is true, now outputs are made. If false, dbprints the status - * @return the number of bits occupied by the samples. - */ -uint32_t DoAcquisition125k_internal(int trigger_threshold,bool silent) -{ - //. - uint8_t *dest = (uint8_t *)BigBuf; - int bufsize = BIGBUF_SIZE; - memset(dest, 0, bufsize); - - if(bits_per_sample < 1) bits_per_sample = 1; - if(bits_per_sample > 8) bits_per_sample = 8; - - if(decimation < 1) decimation = 1; - - // Use a bit stream to handle the output - BitstreamOut data = { dest , 0, 0}; - int sample_counter = 0; - uint8_t sample = 0; - //If we want to do averaging - uint32_t sample_sum =0 ; - uint32_t sample_total_numbers =0 ; - uint32_t sample_total_saved =0 ; - - while(!BUTTON_PRESS()) { - WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - LED_D_OFF(); - if (trigger_threshold != -1 && sample < trigger_threshold) - continue; - - trigger_threshold = -1; - sample_total_numbers++; - - if(averaging) - { - sample_sum += sample; - } - //Check decimation - if(decimation > 1) - { - sample_counter++; - if(sample_counter < decimation) continue; - sample_counter = 0; - } - //Averaging - if(averaging && decimation > 1) { - sample = sample_sum / decimation; - sample_sum =0; - } - //Store the sample - sample_total_saved ++; - if(bits_per_sample == 8){ - dest[sample_total_saved-1] = sample; - data.numbits = sample_total_saved << 3;//Get the return value correct - if(sample_total_saved >= bufsize) break; - } - else{ - pushBit(&data, sample & 0x80); - if(bits_per_sample > 1) pushBit(&data, sample & 0x40); - if(bits_per_sample > 2) pushBit(&data, sample & 0x20); - if(bits_per_sample > 3) pushBit(&data, sample & 0x10); - if(bits_per_sample > 4) pushBit(&data, sample & 0x08); - if(bits_per_sample > 5) pushBit(&data, sample & 0x04); - if(bits_per_sample > 6) pushBit(&data, sample & 0x02); - //Not needed, 8bps is covered above - //if(bits_per_sample > 7) pushBit(&data, sample & 0x01); - if((data.numbits >> 3) +1 >= bufsize) break; - } - } - } - - if(!silent) - { - Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample); - Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); - } - return data.numbits; -} -/** -* Perform sample aquisition. -*/ -void DoAcquisition125k(int trigger_threshold) -{ - DoAcquisition125k_internal(trigger_threshold, false); -} - -/** -* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream -* if not already loaded, sets divisor and starts up the antenna. -* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz -* 0 or 95 ==> 125 KHz -* -**/ -void LFSetupFPGAForADC(int divisor, bool lf_field) -{ - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else if (divisor == 0) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); - - // Connect the A/D to the peak-detected low-frequency path. - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(50); - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); -} -/** -* Initializes the FPGA, and acquires the samples. -**/ -void AcquireRawAdcSamples125k(int divisor,int arg1, int arg2) -{ - if (arg1 != 0) - { - averaging = (arg1 & 0x80) != 0; - bits_per_sample = (arg1 & 0x0F); - } - if(arg2 != 0) - { - decimation = arg2; - } - - Dbprintf("Sampling config: "); - Dbprintf(" divisor: %d ", divisor); - Dbprintf(" bps: %d ", bits_per_sample); - Dbprintf(" decimation: %d ", decimation); - Dbprintf(" averaging: %d ", averaging); - - LFSetupFPGAForADC(divisor, true); - // Now call the acquisition routine - DoAcquisition125k_internal(-1,false); -} -/** -* Initializes the FPGA for snoop-mode, and acquires the samples. -**/ - -void SnoopLFRawAdcSamples(int divisor, int trigger_threshold) -{ - LFSetupFPGAForADC(divisor, false); - DoAcquisition125k(trigger_threshold); -} - void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command) { - /* Make sure the tag is reset */ - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(2500); - - int divisor_used = 95; // 125 KHz // see if 'h' was specified if (command[strlen((char *) command) - 1] == 'h') divisor_used = 88; // 134.8 KHz + sample_config sc = { 0,0,1, divisor_used, 0}; + setSamplingConfig(&sc); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(50); + /* Make sure the tag is reset */ + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(2500); - // And a little more time for the tag to fully power up - SpinDelay(2000); + LFSetupFPGAForADC(sc.divisor, 1); - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); + // And a little more time for the tag to fully power up + SpinDelay(2000); // now modulate the reader field while(*command != '\0' && *command != ' ') { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); LED_D_ON(); @@ -251,14 +64,16 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // now do the read - DoAcquisition125k(-1); + DoAcquisition_config(false); } + + /* blank r/w tag data stream ...0000000000000000 01111111 1010101010101010101010101010101010101010101010101010101010101010 @@ -745,8 +560,8 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition125k_internal(-1,true); - // FSK demodulator + DoAcquisition_default(-1,true); + // FSK demodulator size = HIDdemodFSK(dest, sizeof(BigBuf), &hi2, &hi, &lo); WDT_HIT(); @@ -833,8 +648,8 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition125k_internal(-1,true); - size = sizeof(BigBuf); + DoAcquisition_default(-1,true); + size = sizeof(BigBuf); //Dbprintf("DEBUG: Buffer got"); //askdemod and manchester decode errCnt = askmandemod(dest, &size, &clk, &invert); @@ -884,8 +699,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) while(!BUTTON_PRESS()) { WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition125k_internal(-1,true); - //fskdemod and get start index + DoAcquisition_default(-1,true); + //fskdemod and get start index WDT_HIT(); idx = IOdemodFSK(dest,sizeof(BigBuf)); if (idx>0){ @@ -1489,7 +1304,9 @@ int DemodPCF7931(uint8_t **outBlocks) { int lmin=128, lmax=128; uint8_t dir; - AcquireRawAdcSamples125k(0,0,0); + LFSetupFPGAForADC(95, true); + DoAcquisition_default(0, 0); + lmin = 64; lmax = 192; diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c new file mode 100644 index 000000000..6314ac746 --- /dev/null +++ b/armsrc/lfsampling.c @@ -0,0 +1,251 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Miscellaneous routines for low frequency sampling. +//----------------------------------------------------------------------------- + +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" + +#include "lfsampling.h" + +sample_config config = { 1, 8, 1, 88, 0 } ; + +void printConfig() +{ + Dbprintf("Sampling config: "); + Dbprintf(" [q] divisor: %d ", config.divisor); + Dbprintf(" [b] bps: %d ", config.bits_per_sample); + Dbprintf(" [d] decimation: %d ", config.decimation); + Dbprintf(" [a] averaging: %d ", config.averaging); + Dbprintf(" [t] trigger threshold: %d ", config.trigger_threshold); +} + + +/** + * Called from the USB-handler to set the sampling configuration + * The sampling config is used for std reading and snooping. + * + * Other functions may read samples and ignore the sampling config, + * such as functions to read the UID from a prox tag or similar. + * + * Values set to '0' implies no change (except for averaging) + * @brief setSamplingConfig + * @param sc + */ +void setSamplingConfig(sample_config *sc) +{ + if(sc->divisor != 0) config.divisor = sc->divisor; + if(sc->bits_per_sample!= 0) config.bits_per_sample= sc->bits_per_sample; + if(sc->decimation!= 0) config.decimation= sc->decimation; + if(sc->trigger_threshold != -1) config.trigger_threshold= sc->trigger_threshold; + + config.averaging= sc->averaging; + if(config.bits_per_sample > 8) config.bits_per_sample = 8; + if(config.decimation < 1) config.decimation = 1; + + printConfig(); +} + +sample_config* getSamplingConfig() +{ + return &config; +} + +typedef struct { + uint8_t * buffer; + uint32_t numbits; + uint32_t position; +} BitstreamOut; + + +/** + * @brief Pushes bit onto the stream + * @param stream + * @param bit + */ +void pushBit( BitstreamOut* stream, uint8_t bit) +{ + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = stream->position & 7; + *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); + stream->position++; + stream->numbits++; +} + +/** +* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream +* if not already loaded, sets divisor and starts up the antenna. +* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz +* 0 or 95 ==> 125 KHz +* +**/ +void LFSetupFPGAForADC(int divisor, bool lf_field) +{ + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + else if (divisor == 0) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + else + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); + + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(50); + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); +} + + +/** + * Does the sample acquisition. If threshold is specified, the actual sampling + * is not commenced until the threshold has been reached. + * This method implements decimation and quantization in order to + * be able to provide longer sample traces. + * Uses the following global settings: + * @param decimation - how much should the signal be decimated. A decimation of N means we keep 1 in N samples, etc. + * @param bits_per_sample - bits per sample. Max 8, min 1 bit per sample. + * @param averaging If set to true, decimation will use averaging, so that if e.g. decimation is 3, the sample + * value that will be used is the average value of the three samples. + * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set + * to -1 to ignore threshold. + * @param silent - is true, now outputs are made. If false, dbprints the status + * @return the number of bits occupied by the samples. + */ + +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold,bool silent) +{ + //. + uint8_t *dest = (uint8_t *)BigBuf; + int bufsize = BIGBUF_SIZE; + memset(dest, 0, bufsize); + + if(bits_per_sample < 1) bits_per_sample = 1; + if(bits_per_sample > 8) bits_per_sample = 8; + + if(decimation < 1) decimation = 1; + + // Use a bit stream to handle the output + BitstreamOut data = { dest , 0, 0}; + int sample_counter = 0; + uint8_t sample = 0; + //If we want to do averaging + uint32_t sample_sum =0 ; + uint32_t sample_total_numbers =0 ; + uint32_t sample_total_saved =0 ; + + while(!BUTTON_PRESS()) { + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); + if (trigger_threshold > 0 && sample < trigger_threshold) + continue; + + trigger_threshold = 0; + sample_total_numbers++; + + if(averaging) + { + sample_sum += sample; + } + //Check decimation + if(decimation > 1) + { + sample_counter++; + if(sample_counter < decimation) continue; + sample_counter = 0; + } + //Averaging + if(averaging && decimation > 1) { + sample = sample_sum / decimation; + sample_sum =0; + } + //Store the sample + sample_total_saved ++; + if(bits_per_sample == 8){ + dest[sample_total_saved-1] = sample; + data.numbits = sample_total_saved << 3;//Get the return value correct + if(sample_total_saved >= bufsize) break; + } + else{ + pushBit(&data, sample & 0x80); + if(bits_per_sample > 1) pushBit(&data, sample & 0x40); + if(bits_per_sample > 2) pushBit(&data, sample & 0x20); + if(bits_per_sample > 3) pushBit(&data, sample & 0x10); + if(bits_per_sample > 4) pushBit(&data, sample & 0x08); + if(bits_per_sample > 5) pushBit(&data, sample & 0x04); + if(bits_per_sample > 6) pushBit(&data, sample & 0x02); + //Not needed, 8bps is covered above + //if(bits_per_sample > 7) pushBit(&data, sample & 0x01); + if((data.numbits >> 3) +1 >= bufsize) break; + } + } + } + + if(!silent) + { + Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample",sample_total_saved, sample_total_numbers,bits_per_sample); + Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", + dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + } + return data.numbits; +} +/** + * @brief Does sample acquisition, ignoring the config values set in the sample_config. + * This method is typically used by tag-specific readers who just wants to read the samples + * the normal way + * @param trigger_threshold + * @param silent + * @return number of bits sampled + */ +uint32_t DoAcquisition_default(int trigger_threshold, bool silent) +{ + return DoAcquisition(1,8,0,trigger_threshold,silent); +} +uint32_t DoAcquisition_config( bool silent) +{ + return DoAcquisition(config.decimation + ,config.bits_per_sample + ,config.averaging + ,config.trigger_threshold + ,silent); +} + +uint32_t ReadLF(bool activeField) +{ + printConfig(); + LFSetupFPGAForADC(config.divisor, activeField); + // Now call the acquisition routine + return DoAcquisition_config(false); +} + +/** +* Initializes the FPGA for reader-mode (field on), and acquires the samples. +* @return number of bits sampled +**/ +uint32_t SampleLF() +{ + return ReadLF(true); +} +/** +* Initializes the FPGA for snoop-mode (field off), and acquires the samples. +* @return number of bits sampled +**/ + +uint32_t SnoopLF() +{ + return ReadLF(false); +} diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h new file mode 100644 index 000000000..9ab458f81 --- /dev/null +++ b/armsrc/lfsampling.h @@ -0,0 +1,59 @@ +#ifndef LFSAMPLING_H +#define LFSAMPLING_H + +/** +* Initializes the FPGA for reader-mode (field on), and acquires the samples. +* @return number of bits sampled +**/ +uint32_t SampleLF(); + +/** +* Initializes the FPGA for snoop-mode (field off), and acquires the samples. +* @return number of bits sampled +**/ + +uint32_t SnoopLF(); + +/** + * @brief Does sample acquisition, ignoring the config values set in the sample_config. + * This method is typically used by tag-specific readers who just wants to read the samples + * the normal way + * @param trigger_threshold + * @param silent + * @return number of bits sampled + */ +uint32_t DoAcquisition_default(int trigger_threshold, bool silent); +/** + * @brief Does sample acquisition, using the config values set in the sample_config. + * @param trigger_threshold + * @param silent + * @return number of bits sampled + */ + +uint32_t DoAcquisition_config( bool silent); + +/** +* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream +* if not already loaded, sets divisor and starts up the antenna. +* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz +* 0 or 95 ==> 125 KHz +* +**/ +void LFSetupFPGAForADC(int divisor, bool lf_field); + + +/** + * Called from the USB-handler to set the sampling configuration + * The sampling config is used for std reading and snooping. + * + * Other functions may read samples and ignore the sampling config, + * such as functions to read the UID from a prox tag or similar. + * + * Values set to '0' implies no change (except for averaging) + * @brief setSamplingConfig + * @param sc + */ +void setSamplingConfig(sample_config *sc); + +sample_config * getSamplingConfig(); +#endif // LFSAMPLING_H diff --git a/client/cmddata.c b/client/cmddata.c index 793845807..fa056b679 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -21,6 +21,8 @@ #include "cmdmain.h" #include "cmddata.h" #include "lfdemod.h" +#include "usb_cmd.h" + uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; int DemodBufferLen; static int CmdHelp(const char *Cmd); @@ -1077,11 +1079,15 @@ uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) int CmdSamples(const char *Cmd) { - uint8_t got[40000]; + //If we get all but the last byte in bigbuf, + // we don't have to worry about remaining trash + // in the last byte in case the bits-per-sample + // does not line up on byte boundaries + uint8_t got[40000-1]; int n = strtol(Cmd, NULL, 0); if (n == 0) - n = 20000; + n = sizeof(got); if (n > sizeof(got)) n = sizeof(got); @@ -1091,14 +1097,22 @@ int CmdSamples(const char *Cmd) PrintAndLog("Data fetched"); UsbCommand response; WaitForResponse(CMD_ACK, &response); - uint8_t bits_per_sample = response.arg[0]; - PrintAndLog("Samples packed at %d bits per sample", bits_per_sample); + uint8_t bits_per_sample = 8; + + //Old devices without this feature would send 0 at arg[0] + if(response.arg[0] > 0) + { + sample_config *sc = (sample_config *) response.d.asBytes; + PrintAndLog("Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample + , sc->decimation); + bits_per_sample = sc->bits_per_sample; + } if(bits_per_sample < 8) { PrintAndLog("Unpacking..."); BitstreamOut bout = { got, bits_per_sample * n, 0}; int j =0; - for (j = 0; j * bits_per_sample < n * 8 && j < GraphTraceLen; j++) { + for (j = 0; j * bits_per_sample < n * 8 && j < sizeof(GraphBuffer); j++) { uint8_t sample = getByte(bits_per_sample, &bout); GraphBuffer[j] = ((int) sample )- 128; } @@ -1110,7 +1124,6 @@ int CmdSamples(const char *Cmd) GraphBuffer[j] = ((int)got[j]) - 128; } GraphTraceLen = n; - } RepaintGraphWindow(); diff --git a/client/cmdlf.c b/client/cmdlf.c index 93a9f5866..09d930024 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -356,88 +356,152 @@ int CmdIndalaClone(const char *Cmd) return 0; } -int CmdLFReadUsage() +int usage_lf_read() { - PrintAndLog("Usage: lf read [H|] [b ] [d ] [a 0|1]"); + PrintAndLog("Usage: lf read"); PrintAndLog("Options: "); PrintAndLog(" h This help"); - PrintAndLog(" H High frequency (134 KHz). Defaults to 125 KHz"); - PrintAndLog(" Manually set divisor. 88-> 134KHz, 95-> 125 Hz"); - PrintAndLog(" b Sets resolution of bits per sample. Default (max): 8"); - PrintAndLog(" d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); - PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1"); - PrintAndLog("Examples:"); - PrintAndLog(" lf read"); - PrintAndLog(" Samples at 125KHz, 8bps."); - PrintAndLog(" lf read h b 4 d 3"); - PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with "); - PrintAndLog(" a resolution of 4 bits per sample."); + PrintAndLog("This function takes no arguments. "); + PrintAndLog("Use 'lf config' to set parameters."); return 0; } +int usage_lf_snoop() +{ + PrintAndLog("Usage: lf snoop"); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog("This function takes no arguments. "); + PrintAndLog("Use 'lf config' to set parameters."); + return 0; +} + +int usage_lf_config() +{ + PrintAndLog("Usage: lf config [H|] [b ] [d ] [a 0|1]"); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" L Low frequency (125 KHz)"); + PrintAndLog(" H High frequency (134 KHz)"); + PrintAndLog(" q Manually set divisor. 88-> 134KHz, 95-> 125 Hz"); + PrintAndLog(" b Sets resolution of bits per sample. Default (max): 8"); + PrintAndLog(" d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); + PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1"); + PrintAndLog(" t Sets trigger threshold. 0 means no threshold"); + PrintAndLog("Examples:"); + PrintAndLog(" lf config b 8 L"); + PrintAndLog(" Samples at 125KHz, 8bps."); + PrintAndLog(" lf config H b 4 d 3"); + PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with "); + PrintAndLog(" a resolution of 4 bits per sample."); + PrintAndLog(" lf read"); + PrintAndLog(" Performs a read (active field)"); + PrintAndLog(" lf snoop"); + PrintAndLog(" Performs a snoop (no active field)"); + return 0; +} + +int CmdLFSetConfig(const char *Cmd) +{ + + uint8_t divisor = 0;//Frequency divisor + uint8_t bps = 0; // Bits per sample + uint8_t decimation = 0; //How many to keep + bool averaging = 1; // Defaults to true + bool errors = FALSE; + int trigger_threshold =-1;//Means no change + uint8_t unsigned_trigg = 0; + + uint8_t cmdp =0; + while(param_getchar(Cmd, cmdp) != 0x00) + { + PrintAndLog("working %c", param_getchar(Cmd, cmdp)); + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + return usage_lf_config(); + case 'H': + divisor = 88; + cmdp++; + break; + case 'L': + divisor = 95; + cmdp++; + break; + case 'q': + errors |= param_getdec(Cmd,cmdp+1,&divisor); + cmdp+=2; + break; + case 't': + errors |= param_getdec(Cmd,cmdp+1,&unsigned_trigg); + cmdp+=2; + if(!errors) trigger_threshold = unsigned_trigg; + break; + case 'b': + errors |= param_getdec(Cmd,cmdp+1,&bps); + cmdp+=2; + break; + case 'd': + errors |= param_getdec(Cmd,cmdp+1,&decimation); + cmdp+=2; + break; + case 'a': + averaging = param_getchar(Cmd,cmdp+1) == '1'; + cmdp+=2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + if(errors) break; + } + if(cmdp == 0) + { + errors = 1;// No args + } + + //Validations + if(errors) + { + return usage_lf_config(); + } + //Bps is limited to 8, so fits in lower half of arg1 + if(bps >> 8) bps = 8; + + sample_config config = { + decimation,bps,averaging,divisor,trigger_threshold + }; + //Averaging is a flag on high-bit of arg[1] + UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG}; + memcpy(c.d.asBytes,&config,sizeof(sample_config)); + SendCommand(&c); + return 0; +} + int CmdLFRead(const char *Cmd) { - uint8_t divisor = 95;//Frequency divisor - uint8_t bps = 8; // Bits per sample - uint8_t decimation = 1; //How many to keep - bool averaging = 1; // Should we use averaging when discarding samples? - bool errors = FALSE; uint8_t cmdp =0; if(param_getchar(Cmd, cmdp) == 'h') { - return CmdLFReadUsage(); + return usage_lf_read(); } - - // Divisor - if(param_getchar(Cmd, cmdp) == 'H') { - divisor = 88; - cmdp++; - }else if(param_isdec(Cmd,cmdp) ) - { - errors |= param_getdec(Cmd,cmdp, &divisor); - } - //BPS - if(param_getchar(Cmd, cmdp) == 'b') { - errors |= param_getdec(Cmd,cmdp+1,&bps); - cmdp+=2; - } - //Decimation - if(param_getchar(Cmd, cmdp) == 'd') - { - errors |= param_getdec(Cmd,cmdp+1,&decimation); - cmdp+=2; - } - //Averaging - if(param_getchar(Cmd, cmdp) == 'a') - { - averaging = param_getchar(Cmd,cmdp+1) == '1'; - cmdp+=2; - } - //Validations - if(errors) - { - return CmdLFReadUsage(); - } - - //Bps is limited to 8, so fits in lower half of arg1 - if(bps > 8) bps = 8; - - //Feedback - PrintAndLog("Sampling config: "); - PrintAndLog(" divisor: %d ", divisor); - PrintAndLog(" bps: %d ", bps); - PrintAndLog(" decimation: %d ", decimation); - PrintAndLog(" averaging: %d ", averaging); - PrintAndLog("OBS, this is sticky on the device and affects all LF listening operations"); - PrintAndLog("To reset, issue 'lf read'"); - //And ship it to device - //Averaging is a flag on high-bit of arg[1] UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; - c.arg[0] = divisor; - c.arg[1] = bps | (averaging << 7) ; - c.arg[2] = decimation; + SendCommand(&c); + WaitForResponse(CMD_ACK,NULL); + return 0; +} +int CmdLFSnoop(const char *Cmd) +{ + uint8_t cmdp =0; + if(param_getchar(Cmd, cmdp) == 'h') + { + return usage_lf_snoop(); + } + + UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES}; SendCommand(&c); WaitForResponse(CMD_ACK,NULL); return 0; @@ -517,30 +581,6 @@ int CmdLFSimManchester(const char *Cmd) return 0; } -int CmdLFSnoop(const char *Cmd) -{ - UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES}; - - // 'h' means higher-low-frequency, 134 kHz - c.arg[0] = 0; - c.arg[1] = -1; - - if (*Cmd == 'l') { - sscanf(Cmd, "l %"lli, &c.arg[1]); - } else if(*Cmd == 'h') { - c.arg[0] = 1; - sscanf(Cmd, "h %"lli, &c.arg[1]); - } else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) { - PrintAndLog("usage 1: snoop"); - PrintAndLog(" 2: snoop {l,h} [trigger threshold]"); - PrintAndLog(" 3: snoop [trigger threshold]"); - return 0; - } - - SendCommand(&c); - WaitForResponse(CMD_ACK,NULL); - return 0; -} int CmdVchDemod(const char *Cmd) { @@ -673,12 +713,13 @@ static command_t CommandTable[] = {"help", CmdHelp, 1, "This help"}, {"cmdread", CmdLFCommandRead, 0, " <'0' period> <'1' period> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, {"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"}, + {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"}, {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, {"hid", CmdLFHID, 1, "{ HID RFIDs... }"}, {"io", CmdLFIO, 1, "{ ioProx tags... }"}, {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, {"indalaclone", CmdIndalaClone, 0, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"}, - {"read", CmdLFRead, 0, "['h' or ] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"}, + {"read", CmdLFRead, 0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"}, {"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"}, {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, diff --git a/client/util.c b/client/util.c index bce1c122e..6b47eab9e 100644 --- a/client/util.c +++ b/client/util.c @@ -213,6 +213,7 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) return 0; } + char param_getchar(const char *line, int paramnum) { int bg, en; @@ -228,14 +229,16 @@ uint8_t param_get8(const char *line, int paramnum) } /** - * @brief Reads a decimal integer + * @brief Reads a decimal integer (actually, 0-254, not 255) * @param line * @param paramnum - * @return + * @return -1 if error */ uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination) { - uint8_t val = param_get8ex(line, paramnum, 10, 10); + uint8_t val = param_get8ex(line, paramnum, 255, 10); + printf("read %i", (int8_t ) val); + if( (int8_t) val == -1) return 1; (*destination) = val; return 0; } diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 69c3c1b6a..6ee6509eb 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -33,6 +33,14 @@ typedef struct { uint32_t asDwords[USB_CMD_DATA_SIZE/4]; } d; } PACKED UsbCommand; +// A struct used to send sample-configs over USB +typedef struct{ + uint8_t decimation; + uint8_t bits_per_sample; + bool averaging; + int divisor; + int trigger_threshold; +} sample_config; // For the bootloader #define CMD_DEVICE_INFO 0x0000 @@ -82,6 +90,8 @@ typedef struct { #define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_CLONE_TAG 0x021B #define CMD_EM410X_DEMOD 0x021c +// Sampling configuration for LF reader/snooper +#define CMD_SET_LF_SAMPLING_CONFIG 0x021d /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ @@ -187,6 +197,7 @@ typedef struct { #define FLAG_ICLASS_READER_ONLY_ONCE 0x01 #define FLAG_ICLASS_READER_GET_CC 0x02 + // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: /* Whether a bootloader that understands the common_area is present */ #define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0) From 698b649e0ec1a4fd6c18f518cce1f5c8b79d67b1 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 31 Jan 2015 00:05:04 +0100 Subject: [PATCH 06/11] Added undec to un-decimate data on the client side, so we can use all those sweet demodders even if the data has been decimated on the ARM side --- client/cmddata.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/client/cmddata.c b/client/cmddata.c index fa056b679..964b8031b 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -540,6 +540,35 @@ int CmdDec(const char *Cmd) RepaintGraphWindow(); return 0; } +/** + * Undecimate - I'd call it 'interpolate', but we'll save that + * name until someone does an actual interpolation command, not just + * blindly repeating samples + * @param Cmd + * @return + */ +int CmdUndec(const char *Cmd) +{ + //We have memory, don't we? + int swap[MAX_GRAPH_TRACE_LEN] = { 0 }; + uint32_t i = 0 ,j = 0; + while(j+1 < MAX_GRAPH_TRACE_LEN && i < GraphTraceLen) + { + swap[j] = GraphBuffer[i]; + swap[j+1] = GraphBuffer[i]; + i++; + j+=2; + } + memcpy(GraphBuffer,swap, j); + GraphTraceLen = j; + PrintAndLog("Undecimated by 2"); + RepaintGraphWindow(); + + /* + * Something is not right here, need to look into it, + * the undec seems to only operate on half the values **/ + return 0; +} /* Print our clock rate */ // uses data from graphbuffer @@ -1651,7 +1680,8 @@ static command_t CommandTable[] = {"threshold", CmdThreshold, 1, " -- Maximize/minimize every value in the graph window depending on threshold"}, {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, - {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, + {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, + {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, {NULL, NULL, 0, NULL} }; From c856ceae8acabef3a35a0c70fb4a671d6c5ca292 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Sat, 31 Jan 2015 12:42:40 +0100 Subject: [PATCH 07/11] Fixed undecimation command --- client/cmddata.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 964b8031b..8f73b4007 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -549,24 +549,32 @@ int CmdDec(const char *Cmd) */ int CmdUndec(const char *Cmd) { + if(param_getchar(Cmd, 0) == 'h') + { + PrintAndLog("Usage: data undec [factor]"); + PrintAndLog("This function performs un-decimation, by repeating each sample N times"); + PrintAndLog("Options: "); + PrintAndLog(" h This help"); + PrintAndLog(" factor The number of times to repeat each sample.[default:2]"); + PrintAndLog("Example: 'data undec 3'"); + return 0; + } + + uint8_t factor = param_get8ex(Cmd, 0,2, 10); //We have memory, don't we? int swap[MAX_GRAPH_TRACE_LEN] = { 0 }; - uint32_t i = 0 ,j = 0; - while(j+1 < MAX_GRAPH_TRACE_LEN && i < GraphTraceLen) + uint32_t g_index = 0 ,s_index = 0; + while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN) { - swap[j] = GraphBuffer[i]; - swap[j+1] = GraphBuffer[i]; - i++; - j+=2; + int count = 0; + for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++) + swap[s_index+count] = GraphBuffer[g_index]; + s_index+=count; } - memcpy(GraphBuffer,swap, j); - GraphTraceLen = j; - PrintAndLog("Undecimated by 2"); - RepaintGraphWindow(); - /* - * Something is not right here, need to look into it, - * the undec seems to only operate on half the values **/ + memcpy(GraphBuffer,swap, s_index * sizeof(int)); + GraphTraceLen = s_index; + RepaintGraphWindow(); return 0; } From e9281ae812bd5b30394c78889034e653373f1397 Mon Sep 17 00:00:00 2001 From: Jesse Hallio Date: Tue, 3 Feb 2015 23:22:39 +0200 Subject: [PATCH 08/11] Add flasher from SVN r623 for HID bootprom and current Mac OS X kext --- client/Info.plist | 30 -- client/Makefile | 11 - client/hid-flasher/Info.plist | 50 ++++ client/hid-flasher/Makefile | 48 ++++ client/hid-flasher/elf.h | 71 +++++ client/hid-flasher/flash.c | 478 ++++++++++++++++++++++++++++++++ client/hid-flasher/flash.h | 35 +++ client/hid-flasher/flasher.c | 93 +++++++ client/hid-flasher/obj/.dummy | 0 client/hid-flasher/proxendian.h | 46 +++ client/hid-flasher/proxmark3.h | 17 ++ client/hid-flasher/proxusb.c | 222 +++++++++++++++ client/hid-flasher/proxusb.h | 34 +++ client/hid-flasher/sleep.h | 24 ++ client/hid-flasher/usb_cmd.h | 165 +++++++++++ 15 files changed, 1283 insertions(+), 41 deletions(-) delete mode 100644 client/Info.plist create mode 100644 client/hid-flasher/Info.plist create mode 100644 client/hid-flasher/Makefile create mode 100644 client/hid-flasher/elf.h create mode 100644 client/hid-flasher/flash.c create mode 100644 client/hid-flasher/flash.h create mode 100644 client/hid-flasher/flasher.c create mode 100644 client/hid-flasher/obj/.dummy create mode 100644 client/hid-flasher/proxendian.h create mode 100644 client/hid-flasher/proxmark3.h create mode 100644 client/hid-flasher/proxusb.c create mode 100644 client/hid-flasher/proxusb.h create mode 100644 client/hid-flasher/sleep.h create mode 100644 client/hid-flasher/usb_cmd.h diff --git a/client/Info.plist b/client/Info.plist deleted file mode 100644 index d1f87572f..000000000 --- a/client/Info.plist +++ /dev/null @@ -1,30 +0,0 @@ - - - - - CFBundleDevelopmentRegion English - CFBundleIdentifier org.proxmark - CFBundleIconFile - CFBundleInfoDictionaryVersion 6.0 - CFBundlePackageType KEXT - CFBundleSignature ???? - CFBundleVersion 1.0.0 - IOKitPersonalities - - Proxmark3 - - CFBundleIdentifiercom.apple.kernel.iokit - IOClassIOService - IOProviderClassIOUSBInterface - bConfigurationValue 1 - bInterfaceNumber 0 - idProduct19343 - idVendor39620 - - - OSBundleLibraries - - com.apple.iokit.IOUSBFamily1.8 - - - diff --git a/client/Makefile b/client/Makefile index 823ee4459..e63581ba1 100644 --- a/client/Makefile +++ b/client/Makefile @@ -137,17 +137,6 @@ clean: tarbin: $(BINS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) -# must be run as root -install_kext: Info.plist - mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents - cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents - chown -R root:wheel /System/Library/Extensions/Proxmark3.kext - chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents - chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist - rm -rf /System/Library/Caches/com.apple.kext.caches - touch /System/Library/Extensions - @echo "*** You may need to reboot for the kext to take effect." - lua_build: @echo Compiling liblua, using platform $(LUAPLATFORM) cd ../liblua && make $(LUAPLATFORM) diff --git a/client/hid-flasher/Info.plist b/client/hid-flasher/Info.plist new file mode 100644 index 000000000..c78a68bae --- /dev/null +++ b/client/hid-flasher/Info.plist @@ -0,0 +1,50 @@ + + + + + + + + + CFBundleDevelopmentRegion + English + CFBundleIconFile + + CFBundleIdentifier + com.proxmark.driver.dummy + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + KEXT + CFBundleSignature + ???? + CFBundleVersion + 1.0.0d2 + IOKitPersonalities + + + Proxmark3 + + CFBundleIdentifier + com.apple.kpi.iokit + IOClass + IOService + IOProviderClass + IOUSBInterface + bConfigurationValue + 1 + bInterfaceNumber + 0 + idProduct + 19343 + idVendor + 39620 + + + OSBundleLibraries + + com.apple.iokit.IOUSBFamily + 1.8 + + + diff --git a/client/hid-flasher/Makefile b/client/hid-flasher/Makefile new file mode 100644 index 000000000..5e9b6fcde --- /dev/null +++ b/client/hid-flasher/Makefile @@ -0,0 +1,48 @@ +#----------------------------------------------------------------------------- +# This code is licensed to you under the terms of the GNU GPL, version 2 or, +# at your option, any later version. See the LICENSE.txt file for the text of +# the license. +#----------------------------------------------------------------------------- +include ../../common/Makefile.common + +CC=gcc +CXX=g++ +#COMMON_FLAGS = -m32 + +VPATH = ../../common +OBJDIR = obj + +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lusb -lreadline -lpthread +LDFLAGS = $(COMMON_FLAGS) +CFLAGS = -std=gnu99 -I. -I../include -I../common -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) -g -O3 + +CXXFLAGS = +QTLDLIBS = + +RM = rm -f +BINS = flasher +CLEAN = flasher flasher.exe $(OBJDIR)/*.o *.o + +all: $(BINS) + +flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(OBJDIR)/proxusb.o + $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ + +$(OBJDIR)/%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + $(RM) $(CLEAN) + +# must be run as root +install_kext: Info.plist + mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents + cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents + chown -R root:wheel /System/Library/Extensions/Proxmark3.kext + chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents + chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist + rm -rf /System/Library/Caches/com.apple.kext.caches + touch /System/Library/Extensions + @echo "*** You may need to reboot for the kext to take effect." + +.PHONY: all clean diff --git a/client/hid-flasher/elf.h b/client/hid-flasher/elf.h new file mode 100644 index 000000000..90e203353 --- /dev/null +++ b/client/hid-flasher/elf.h @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// ELF header +//----------------------------------------------------------------------------- + +#ifndef __ELF_H__ +#define __ELF_H__ + +typedef struct { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} __attribute__((__packed__)) Elf32_Phdr; + +#define EI_NIDENT 16 + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shtrndx; +} __attribute__((__packed__)) Elf32_Ehdr; + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 + +#define ELFCLASS32 1 +#define ELFCLASS64 2 + +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_CURRENT 1 + +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 + +#define EM_ARM 0x28 + +#define PF_R 4 +#define PF_W 2 +#define PF_X 1 + +#endif + diff --git a/client/hid-flasher/flash.c b/client/hid-flasher/flash.c new file mode 100644 index 000000000..6670d637d --- /dev/null +++ b/client/hid-flasher/flash.c @@ -0,0 +1,478 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Hector Martin "marcan" +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// ELF file flasher +//----------------------------------------------------------------------------- + +#include +#include +#include +#include "sleep.h" +#include "proxusb.h" +#include "flash.h" +#include "elf.h" +#include "proxendian.h" + +// FIXME: what the fuckity fuck +unsigned int current_command = CMD_UNKNOWN; + +#define FLASH_START 0x100000 +#define FLASH_SIZE (256*1024) +#define FLASH_END (FLASH_START + FLASH_SIZE) +#define BOOTLOADER_SIZE 0x2000 +#define BOOTLOADER_END (FLASH_START + BOOTLOADER_SIZE) + +#define BLOCK_SIZE 0x100 + +static const uint8_t elf_ident[] = { + 0x7f, 'E', 'L', 'F', + ELFCLASS32, + ELFDATA2LSB, + EV_CURRENT +}; + +// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent +// unaligned segments if needed +static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs) +{ + Elf32_Phdr *phdr = phdrs; + flash_seg_t *seg; + uint32_t last_end = 0; + + ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs); + if (!ctx->segments) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + ctx->num_segs = 0; + seg = ctx->segments; + + fprintf(stderr, "Loading usable ELF segments:\n"); + for (int i = 0; i < num_phdrs; i++) { + if (le32(phdr->p_type) != PT_LOAD) { + phdr++; + continue; + } + uint32_t vaddr = le32(phdr->p_vaddr); + uint32_t paddr = le32(phdr->p_paddr); + uint32_t filesz = le32(phdr->p_filesz); + uint32_t memsz = le32(phdr->p_memsz); + uint32_t offset = le32(phdr->p_offset); + uint32_t flags = le32(phdr->p_flags); + if (!filesz) { + phdr++; + continue; + } + fprintf(stderr, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n", + i, vaddr, paddr, filesz, memsz, + flags & PF_R ? 'R' : ' ', + flags & PF_W ? 'W' : ' ', + flags & PF_X ? 'X' : ' ', + offset); + if (filesz != memsz) { + fprintf(stderr, "Error: PHDR file size does not equal memory size\n" + "(DATA+BSS PHDRs do not make sense on ROM platforms!)\n"); + return -1; + } + if (paddr < last_end) { + fprintf(stderr, "Error: PHDRs not sorted or overlap\n"); + return -1; + } + if (paddr < FLASH_START || (paddr+filesz) > FLASH_END) { + fprintf(stderr, "Error: PHDR is not contained in Flash\n"); + return -1; + } + if (vaddr >= FLASH_START && vaddr < FLASH_END && (flags & PF_W)) { + fprintf(stderr, "Error: Flash VMA segment is writable\n"); + return -1; + } + + uint8_t *data; + // make extra space if we need to move the data forward + data = malloc(filesz + BLOCK_SIZE); + if (!data) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) { + fprintf(stderr, "Error while reading PHDR payload\n"); + free(data); + return -1; + } + + uint32_t block_offset = paddr & (BLOCK_SIZE-1); + if (block_offset) { + if (ctx->num_segs) { + flash_seg_t *prev_seg = seg - 1; + uint32_t this_end = paddr + filesz; + uint32_t this_firstblock = paddr & ~(BLOCK_SIZE-1); + uint32_t prev_lastblock = (last_end - 1) & ~(BLOCK_SIZE-1); + + if (this_firstblock == prev_lastblock) { + uint32_t new_length = this_end - prev_seg->start; + uint32_t this_offset = paddr - prev_seg->start; + uint32_t hole = this_offset - prev_seg->length; + uint8_t *new_data = malloc(new_length); + if (!new_data) { + fprintf(stderr, "Out of memory\n"); + free(data); + return -1; + } + memset(new_data, 0xff, new_length); + memcpy(new_data, prev_seg->data, prev_seg->length); + memcpy(new_data + this_offset, data, filesz); + fprintf(stderr, "Note: Extending previous segment from 0x%x to 0x%x bytes\n", + prev_seg->length, new_length); + if (hole) + fprintf(stderr, "Note: 0x%x-byte hole created\n", hole); + free(data); + free(prev_seg->data); + prev_seg->data = new_data; + prev_seg->length = new_length; + last_end = this_end; + phdr++; + continue; + } + } + fprintf(stderr, "Warning: segment does not begin on a block boundary, will pad\n"); + memmove(data + block_offset, data, filesz); + memset(data, 0xFF, block_offset); + filesz += block_offset; + paddr -= block_offset; + } + + seg->data = data; + seg->start = paddr; + seg->length = filesz; + seg++; + ctx->num_segs++; + + last_end = paddr + filesz; + phdr++; + } + return 0; +} + +// Sanity check segments and check for bootloader writes +static int check_segs(flash_file_t *ctx, int can_write_bl) { + for (int i = 0; i < ctx->num_segs; i++) { + flash_seg_t *seg = &ctx->segments[i]; + + if (seg->start & (BLOCK_SIZE-1)) { + fprintf(stderr, "Error: Segment is not aligned\n"); + return -1; + } + if (seg->start < FLASH_START) { + fprintf(stderr, "Error: Segment is outside of flash bounds\n"); + return -1; + } + if (seg->start + seg->length > FLASH_END) { + fprintf(stderr, "Error: Segment is outside of flash bounds\n"); + return -1; + } + if (!can_write_bl && seg->start < BOOTLOADER_END) { + fprintf(stderr, "Attempted to write bootloader but bootloader writes are not enabled\n"); + return -1; + } + } + return 0; +} + +// Load an ELF file and prepare it for flashing +int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) +{ + FILE *fd = NULL; + Elf32_Ehdr ehdr; + Elf32_Phdr *phdrs = NULL; + int num_phdrs; + int res; + + fd = fopen(name, "rb"); + if (!fd) { + fprintf(stderr, "Could not open file '%s': ", name); + perror(NULL); + goto fail; + } + + fprintf(stderr, "Loading ELF file '%s'...\n", name); + + if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { + fprintf(stderr, "Error while reading ELF file header\n"); + goto fail; + } + if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident)) + || le32(ehdr.e_version) != 1) + { + fprintf(stderr, "Not an ELF file or wrong ELF type\n"); + goto fail; + } + if (le16(ehdr.e_type) != ET_EXEC) { + fprintf(stderr, "ELF is not executable\n"); + goto fail; + } + if (le16(ehdr.e_machine) != EM_ARM) { + fprintf(stderr, "Wrong ELF architecture\n"); + goto fail; + } + if (!ehdr.e_phnum || !ehdr.e_phoff) { + fprintf(stderr, "ELF has no PHDRs\n"); + goto fail; + } + if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) { + // could be a structure padding issue... + fprintf(stderr, "Either the ELF file or this code is made of fail\n"); + goto fail; + } + num_phdrs = le16(ehdr.e_phnum); + + phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr)); + if (!phdrs) { + fprintf(stderr, "Out of memory\n"); + goto fail; + } + if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) { + fprintf(stderr, "Error while reading ELF PHDRs\n"); + goto fail; + } + if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) { + fprintf(stderr, "Error while reading ELF PHDRs\n"); + goto fail; + } + + res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs); + if (res < 0) + goto fail; + res = check_segs(ctx, can_write_bl); + if (res < 0) + goto fail; + + free(phdrs); + fclose(fd); + ctx->filename = name; + return 0; + +fail: + if (phdrs) + free(phdrs); + if (fd) + fclose(fd); + flash_free(ctx); + return -1; +} + +// Get the state of the proxmark, backwards compatible +static int get_proxmark_state(uint32_t *state) +{ + UsbCommand c; + c.cmd = CMD_DEVICE_INFO; + SendCommand(&c); + + UsbCommand resp; + ReceiveCommand(&resp); + + // Three outcomes: + // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK + // 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command" + // 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags + + switch (resp.cmd) { + case CMD_ACK: + *state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM; + break; + case CMD_DEBUG_PRINT_STRING: + *state = DEVICE_INFO_FLAG_CURRENT_MODE_OS; + break; + case CMD_DEVICE_INFO: + *state = resp.arg[0]; + break; + default: + fprintf(stderr, "Error: Couldn't get proxmark state, bad response type: 0x%04x\n", resp.cmd); + return -1; + break; + } + + return 0; +} + +// Enter the bootloader to be able to start flashing +static int enter_bootloader(void) +{ + uint32_t state; + + if (get_proxmark_state(&state) < 0) + return -1; + + if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) { + /* Already in flash state, we're done. */ + return 0; + } + + if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { + fprintf(stderr,"Entering bootloader...\n"); + UsbCommand c; + memset(&c, 0, sizeof (c)); + + if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT) + && (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT)) + { + // New style handover: Send CMD_START_FLASH, which will reset the board + // and enter the bootrom on the next boot. + c.cmd = CMD_START_FLASH; + SendCommand(&c); + fprintf(stderr,"(Press and release the button only to abort)\n"); + } else { + // Old style handover: Ask the user to press the button, then reset the board + c.cmd = CMD_HARDWARE_RESET; + SendCommand(&c); + fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n"); + } + fprintf(stderr,"Waiting for Proxmark to reappear on USB..."); + + CloseProxmark(); + sleep(1); + while (!OpenProxmark(0)) { + sleep(1); + fprintf(stderr, "."); + } + fprintf(stderr," Found.\n"); + + return 0; + } + + fprintf(stderr, "Error: Unknown Proxmark mode\n"); + return -1; +} + +static int wait_for_ack(void) +{ + UsbCommand ack; + ReceiveCommand(&ack); + if (ack.cmd != CMD_ACK) { + printf("Error: Unexpected reply 0x%04x (expected ACK)\n", ack.cmd); + return -1; + } + return 0; +} + +// Go into flashing mode +int flash_start_flashing(int enable_bl_writes) +{ + uint32_t state; + + if (enter_bootloader() < 0) + return -1; + + if (get_proxmark_state(&state) < 0) + return -1; + + if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) { + // This command is stupid. Why the heck does it care which area we're + // flashing, as long as it's not the bootloader area? The mind boggles. + UsbCommand c = {CMD_START_FLASH}; + + if (enable_bl_writes) { + c.arg[0] = FLASH_START; + c.arg[1] = FLASH_END; + c.arg[2] = START_FLASH_MAGIC; + } else { + c.arg[0] = BOOTLOADER_END; + c.arg[1] = FLASH_END; + c.arg[2] = 0; + } + SendCommand(&c); + return wait_for_ack(); + } else { + fprintf(stderr, "Note: Your bootloader does not understand the new START_FLASH command\n"); + fprintf(stderr, " It is recommended that you update your bootloader\n\n"); + } + + return 0; +} + +static int write_block(uint32_t address, uint8_t *data, uint32_t length) +{ + uint8_t block_buf[BLOCK_SIZE]; + + memset(block_buf, 0xFF, BLOCK_SIZE); + memcpy(block_buf, data, length); + + UsbCommand c = {CMD_SETUP_WRITE}; + for (int i = 0; i < 240; i += 48) { + memcpy(c.d.asBytes, block_buf + i, 48); + c.arg[0] = i / 4; + SendCommand(&c); + if (wait_for_ack() < 0) + return -1; + } + + c.cmd = CMD_FINISH_WRITE; + c.arg[0] = address; + memcpy(c.d.asBytes, block_buf+240, 16); + SendCommand(&c); + return wait_for_ack(); +} + +// Write a file's segments to Flash +int flash_write(flash_file_t *ctx) +{ + fprintf(stderr, "Writing segments for file: %s\n", ctx->filename); + for (int i = 0; i < ctx->num_segs; i++) { + flash_seg_t *seg = &ctx->segments[i]; + + uint32_t length = seg->length; + uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; + uint32_t end = seg->start + length; + + fprintf(stderr, " 0x%08x..0x%08x [0x%x / %d blocks]", + seg->start, end - 1, length, blocks); + + int block = 0; + uint8_t *data = seg->data; + uint32_t baddr = seg->start; + + while (length) { + uint32_t block_size = length; + if (block_size > BLOCK_SIZE) + block_size = BLOCK_SIZE; + + if (write_block(baddr, data, block_size) < 0) { + fprintf(stderr, " ERROR\n"); + fprintf(stderr, "Error writing block %d of %d\n", block, blocks); + return -1; + } + + data += block_size; + baddr += block_size; + length -= block_size; + block++; + fprintf(stderr, "."); + } + fprintf(stderr, " OK\n"); + } + return 0; +} + +// free a file context +void flash_free(flash_file_t *ctx) +{ + if (!ctx) + return; + if (ctx->segments) { + for (int i = 0; i < ctx->num_segs; i++) + free(ctx->segments[i].data); + free(ctx->segments); + ctx->segments = NULL; + ctx->num_segs = 0; + } +} + +// just reset the unit +int flash_stop_flashing(void) { + UsbCommand c = {CMD_HARDWARE_RESET}; + SendCommand(&c); + return 0; +} diff --git a/client/hid-flasher/flash.h b/client/hid-flasher/flash.h new file mode 100644 index 000000000..d5f47b9d4 --- /dev/null +++ b/client/hid-flasher/flash.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Flashing utility functions +//----------------------------------------------------------------------------- + +#ifndef __FLASH_H__ +#define __FLASH_H__ + +#include +#include "elf.h" + +typedef struct { + void *data; + uint32_t start; + uint32_t length; +} flash_seg_t; + +typedef struct { + const char *filename; + int can_write_bl; + int num_segs; + flash_seg_t *segments; +} flash_file_t; + +int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); +int flash_start_flashing(int enable_bl_writes); +int flash_write(flash_file_t *ctx); +void flash_free(flash_file_t *ctx); +int flash_stop_flashing(void); + +#endif + diff --git a/client/hid-flasher/flasher.c b/client/hid-flasher/flasher.c new file mode 100644 index 000000000..a4a0e85e7 --- /dev/null +++ b/client/hid-flasher/flasher.c @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Flasher frontend tool +//----------------------------------------------------------------------------- + +#include +#include +#include +#include "sleep.h" +#include "proxusb.h" +#include "flash.h" + +static void usage(char *argv0) +{ + fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); + fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); + fprintf(stderr, "Example: %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0); +} + +#define MAX_FILES 4 + +int main(int argc, char **argv) +{ + int can_write_bl = 0; + int num_files = 0; + int res; + flash_file_t files[MAX_FILES]; + + memset(files, 0, sizeof(files)); + + if (argc < 2) { + usage(argv[0]); + return -1; + } + + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (!strcmp(argv[i], "-b")) { + can_write_bl = 1; + } else { + usage(argv[0]); + return -1; + } + } else { + res = flash_load(&files[num_files], argv[i], can_write_bl); + if (res < 0) { + fprintf(stderr, "Error while loading %s\n", argv[i]); + return -1; + } + fprintf(stderr, "\n"); + num_files++; + } + } + + usb_init(); + + fprintf(stderr, "Waiting for Proxmark to appear on USB..."); + while (!OpenProxmark(1)) { + sleep(1); + fprintf(stderr, "."); + } + fprintf(stderr, " Found.\n"); + + res = flash_start_flashing(can_write_bl); + if (res < 0) + return -1; + + fprintf(stderr, "\nFlashing...\n"); + + for (int i = 0; i < num_files; i++) { + res = flash_write(&files[i]); + if (res < 0) + return -1; + flash_free(&files[i]); + fprintf(stderr, "\n"); + } + + fprintf(stderr, "Resetting hardware...\n"); + + res = flash_stop_flashing(); + if (res < 0) + return -1; + + CloseProxmark(); + + fprintf(stderr, "All done.\n\n"); + fprintf(stderr, "Have a nice day!\n"); + + return 0; +} diff --git a/client/hid-flasher/obj/.dummy b/client/hid-flasher/obj/.dummy new file mode 100644 index 000000000..e69de29bb diff --git a/client/hid-flasher/proxendian.h b/client/hid-flasher/proxendian.h new file mode 100644 index 000000000..4a386a0dd --- /dev/null +++ b/client/hid-flasher/proxendian.h @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Hector Martin "marcan" +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Endianness convenience functions +//----------------------------------------------------------------------------- + +#ifndef PROXENDIAN_H__ +#define PROXENDIAN_H__ + +#include + +#ifdef WIN32 +# define HOST_LITTLE_ENDIAN +#else +# include + +# if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +# error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +# endif + +# if BYTE_ORDER == LITTLE_ENDIAN +# define HOST_LITTLE_ENDIAN +# endif +#endif + +#ifdef HOST_LITTLE_ENDIAN +# define le16(x) (x) +# define le32(x) (x) +#else + +static inline uint16_t le16(uint16_t v) +{ + return (v>>8) | (v<<8); +} + +static inline uint32_t le32(uint32_t v) +{ + return (le16(v)<<16) | (le16(v>>16)); +} +#endif // HOST_LITTLE_ENDIAN + +#endif // PROXENDIAN_H__ diff --git a/client/hid-flasher/proxmark3.h b/client/hid-flasher/proxmark3.h new file mode 100644 index 000000000..f5dd2b7fa --- /dev/null +++ b/client/hid-flasher/proxmark3.h @@ -0,0 +1,17 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Main binary +//----------------------------------------------------------------------------- + +#ifndef PROXMARK3_H__ +#define PROXMARK3_H__ + +#define PROXPROMPT "proxmark3> " + +#endif diff --git a/client/hid-flasher/proxusb.c b/client/hid-flasher/proxusb.c new file mode 100644 index 000000000..3c2b20b4c --- /dev/null +++ b/client/hid-flasher/proxusb.c @@ -0,0 +1,222 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// USB utilities +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sleep.h" +#include "proxusb.h" +#include "proxmark3.h" +#include "usb_cmd.h" + +// It seems to be missing for mingw +#ifndef ETIMEDOUT +#define ETIMEDOUT 116 +#endif + +usb_dev_handle *devh = NULL; +static unsigned int claimed_iface = 0; +unsigned char return_on_error = 0; +unsigned char error_occured = 0; +extern unsigned int current_command; + +void SendCommand(UsbCommand *c) +{ + int ret; + +#if 0 + printf("Sending %d bytes\n", sizeof(UsbCommand)); +#endif + current_command = c->cmd; + ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000); + if (ret<0) { + error_occured = 1; + if (return_on_error) + return; + + fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n", + usb_strerror()); + + if (devh) { + usb_close(devh); + devh = NULL; + } + while(!OpenProxmark(0)) { sleep(1); } + printf(PROXPROMPT); + fflush(NULL); + + return; + } +} + +bool ReceiveCommandPoll(UsbCommand *c) +{ + int ret; + + memset(c, 0, sizeof (UsbCommand)); + ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500); + if (ret<0) { + if (ret != -ETIMEDOUT) { + error_occured = 1; + if (return_on_error) + return false; + + fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n", + usb_strerror(), ret); + + if (devh) { + usb_close(devh); + devh = NULL; + } + while(!OpenProxmark(0)) { sleep(1); } + printf(PROXPROMPT); + fflush(NULL); + + return false; + } + } else { + if (ret && (ret < sizeof(UsbCommand))) { + fprintf(stderr, "Read only %d instead of requested %d bytes!\n", + ret, (int)sizeof(UsbCommand)); + } + } + + return ret > 0; +} + +void ReceiveCommand(UsbCommand *c) +{ +// printf("%s()\n", __FUNCTION__); + int retval = 0; + do { + retval = ReceiveCommandPoll(c); + if (retval != 1) printf("ReceiveCommandPoll returned %d\n", retval); + } while(retval<0); +// printf("recv %x\n", c->cmd); +} + +usb_dev_handle* findProxmark(int verbose, unsigned int *iface) +{ + struct usb_bus *busses, *bus; + usb_dev_handle *handle = NULL; + struct prox_unit units[50]; + int iUnit = 0; + + 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 fabiled: %s!\n", usb_strerror()); + //return NULL; + continue; + } + *iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber; + + struct prox_unit unit = {handle, {0}}; + usb_get_string_simple(handle, desc->iSerialNumber, unit.serial_number, sizeof(unit.serial_number)); + units[iUnit++] = unit; + + //return handle; + } + } + } + + if (iUnit > 0) { + int iSelection = 0; + + fprintf(stdout, "\nConnected units:\n"); + + for (int i = 0; i < iUnit; i++) { + struct usb_device * dev = usb_device(units[i].handle); + fprintf(stdout, "\t%d. SN: %s [%s/%s]\n", i+1, units[i].serial_number, dev->bus->dirname, dev->filename); + } + if (iUnit > 1) { + while (iSelection < 1 || iSelection > iUnit) { + fprintf(stdout, "Which unit do you want to connect to? "); + fscanf(stdin, "%d", &iSelection); + } + } + else + iSelection = 1; + iSelection --; + + for (int i = 0; i < iUnit; i++) { + if (iSelection == i) continue; + usb_close(units[i].handle); + units[i].handle = NULL; + } + + return units[iSelection].handle; + } + + return NULL; +} + +usb_dev_handle* OpenProxmark(int verbose) +{ + int ret; + usb_dev_handle *handle = NULL; + unsigned int iface; + + handle = findProxmark(verbose, &iface); + if (!handle) + return NULL; + +#ifdef __linux__ + /* 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 + + // Needed for Windows. Optional for Mac OS and Linux + ret = usb_set_configuration(handle, 1); + if (ret < 0) { + if (verbose) + fprintf(stderr, "configuration set failed: %s!\n", usb_strerror()); + return NULL; + } + + 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); + devh = NULL; +} diff --git a/client/hid-flasher/proxusb.h b/client/hid-flasher/proxusb.h new file mode 100644 index 000000000..5845888a5 --- /dev/null +++ b/client/hid-flasher/proxusb.h @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// USB utilities +//----------------------------------------------------------------------------- + +#ifndef PROXUSB_H__ +#define PROXUSB_H__ + +#include +#include +#include +#include "usb_cmd.h" + +extern unsigned char return_on_error; +extern unsigned char error_occured; + +void SendCommand(UsbCommand *c); +bool ReceiveCommandPoll(UsbCommand *c); +void ReceiveCommand(UsbCommand *c); +struct usb_dev_handle* FindProxmark(int verbose, unsigned int *iface); +struct usb_dev_handle* OpenProxmark(int verbose); +void CloseProxmark(void); + +struct prox_unit { + usb_dev_handle *handle; + char serial_number[256]; +}; + +#endif diff --git a/client/hid-flasher/sleep.h b/client/hid-flasher/sleep.h new file mode 100644 index 000000000..81f4e0603 --- /dev/null +++ b/client/hid-flasher/sleep.h @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// platform-independant sleep macros +//----------------------------------------------------------------------------- + +#ifndef SLEEP_H__ +#define SLEEP_H__ + +#ifdef WIN32 +#include +#define sleep(n) Sleep(1000 * n) +#define msleep(n) Sleep(n) +#else +#include +#define msleep(n) usleep(1000 * n) +#endif + +#endif + diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h new file mode 100644 index 000000000..a7552b3ec --- /dev/null +++ b/client/hid-flasher/usb_cmd.h @@ -0,0 +1,165 @@ +//----------------------------------------------------------------------------- +// Jonathan Westhues, Mar 2006 +// Edits by Gerhard de Koning Gans, Sep 2007 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Definitions for all the types of commands that may be sent over USB; our +// own protocol. +//----------------------------------------------------------------------------- + +#ifndef __USB_CMD_H +#define __USB_CMD_H +#ifdef _MSC_VER +typedef DWORD uint32_t; +typedef BYTE uint8_t; +#define PACKED +// stuff +#else +#include +#include +#define PACKED __attribute__((packed)) +#endif + +typedef struct { + uint32_t cmd; + uint32_t arg[3]; + union { + uint8_t asBytes[48]; + uint32_t asDwords[12]; + } d; +} PACKED UsbCommand; + +// For the bootloader +#define CMD_DEVICE_INFO 0x0000 +#define CMD_SETUP_WRITE 0x0001 +#define CMD_FINISH_WRITE 0x0003 +#define CMD_HARDWARE_RESET 0x0004 +#define CMD_START_FLASH 0x0005 +#define CMD_NACK 0x00fe +#define CMD_ACK 0x00ff + +// For general mucking around +#define CMD_DEBUG_PRINT_STRING 0x0100 +#define CMD_DEBUG_PRINT_INTEGERS 0x0101 +#define CMD_DEBUG_PRINT_BYTES 0x0102 +#define CMD_LCD_RESET 0x0103 +#define CMD_LCD 0x0104 +#define CMD_BUFF_CLEAR 0x0105 +#define CMD_READ_MEM 0x0106 +#define CMD_VERSION 0x0107 + +// For low-frequency tags +#define CMD_READ_TI_TYPE 0x0202 +#define CMD_WRITE_TI_TYPE 0x0203 +#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204 +#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205 +#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206 +#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207 +#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208 +#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0209 +#define CMD_SIMULATE_TAG_125K 0x020A +#define CMD_HID_DEMOD_FSK 0x020B +#define CMD_HID_SIM_TAG 0x020C +#define CMD_SET_LF_DIVISOR 0x020D +#define CMD_LF_SIMULATE_BIDIR 0x020E +#define CMD_SET_ADC_MUX 0x020F +#define CMD_HID_CLONE_TAG 0x0210 +#define CMD_EM410X_WRITE_TAG 0x0211 +#define CMD_INDALA_CLONE_TAG 0x0212 +// for 224 bits UID +#define CMD_INDALA_CLONE_TAG_L 0x0213 + +/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ + +// For the 13.56 MHz tags +#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 +#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 +#define CMD_READ_SRI512_TAG 0x0303 +#define CMD_READ_SRIX4K_TAG 0x0304 +#define CMD_READER_ISO_15693 0x0310 +#define CMD_SIMTAG_ISO_15693 0x0311 +#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312 +#define CMD_ISO_15693_COMMAND 0x0313 +#define CMD_ISO_15693_COMMAND_DONE 0x0314 +#define CMD_ISO_15693_FIND_AFI 0x0315 +#define CMD_ISO_15693_DEBUG 0x0316 + +// For Hitag2 transponders +#define CMD_SNOOP_HITAG 0x0370 +#define CMD_SIMULATE_HITAG 0x0371 +#define CMD_READER_HITAG 0x0372 + +#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 +#define CMD_SIMULATE_TAG_ISO_14443 0x0381 +#define CMD_SNOOP_ISO_14443 0x0382 +#define CMD_SNOOP_ISO_14443a 0x0383 +#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 +#define CMD_READER_ISO_14443a 0x0385 +#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387 +#define CMD_READER_LEGIC_RF 0x0388 +#define CMD_WRITER_LEGIC_RF 0x0389 +#define CMD_EPA_PACE_COLLECT_NONCE 0x038A + +#define CMD_SNOOP_ICLASS 0x0392 +#define CMD_SIMULATE_TAG_ICLASS 0x0393 +#define CMD_READER_ICLASS 0x0394 + +// For measurements of the antenna tuning +#define CMD_MEASURE_ANTENNA_TUNING 0x0400 +#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401 +#define CMD_MEASURED_ANTENNA_TUNING 0x0410 +#define CMD_LISTEN_READER_FIELD 0x0420 + +// For direct FPGA control +#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 + +// For mifare commands +#define CMD_MIFARE_SET_DBGMODE 0x0600 +#define CMD_MIFARE_EML_MEMCLR 0x0601 +#define CMD_MIFARE_EML_MEMSET 0x0602 +#define CMD_MIFARE_EML_MEMGET 0x0603 +#define CMD_MIFARE_EML_CARDLOAD 0x0604 +#define CMD_MIFARE_EML_CSETBLOCK 0x0605 +#define CMD_MIFARE_EML_CGETBLOCK 0x0606 + +#define CMD_SIMULATE_MIFARE_CARD 0x0610 + +#define CMD_READER_MIFARE 0x0611 +#define CMD_MIFARE_NESTED 0x0612 + +#define CMD_MIFARE_READBL 0x0620 +#define CMD_MIFARE_READSC 0x0621 +#define CMD_MIFARE_WRITEBL 0x0622 +#define CMD_MIFARE_CHKKEYS 0x0623 + +#define CMD_MIFARE_SNIFFER 0x0630 + +#define CMD_UNKNOWN 0xFFFF + +// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: +/* Whether a bootloader that understands the common_area is present */ +#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0) + +/* Whether a osimage that understands the common_area is present */ +#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1) + +/* Set if the bootloader is currently executing */ +#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2) + +/* Set if the OS is currently executing */ +#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3) + +/* Set if this device understands the extend start flash command */ +#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4) + +/* CMD_START_FLASH may have three arguments: start of area to flash, + end of area to flash, optional magic. + The bootrom will not allow to overwrite itself unless this magic + is given as third parameter */ + +#define START_FLASH_MAGIC 0x54494f44 // 'DOIT' + +#endif From a6cfa75035727fd0572b4cf0ba1ca9c731f91782 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 4 Feb 2015 11:40:49 +0100 Subject: [PATCH 09/11] add: lots of new toytypes in default_toys.lua fix: mixture between dec & hex numbers caused wrongly identifications of toytypes (default_toys.lua) add: showing bytes for trap-types in tnp3dump.lua --- client/lualibs/default_toys.lua | 224 +++++++++++++++++++++++++------- client/scripts/tnp3dump.lua | 9 +- 2 files changed, 184 insertions(+), 49 deletions(-) diff --git a/client/lualibs/default_toys.lua b/client/lualibs/default_toys.lua index abb565154..cd839ca1e 100644 --- a/client/lualibs/default_toys.lua +++ b/client/lualibs/default_toys.lua @@ -1,63 +1,195 @@ local _names = { --[[ --]] - ["0400"]="BASH", - ["1600"]="BOOMER" , - ["1800"]="CAMO", - ["3000"]="CHOPCHOP" , - ["2000"]="CYNDER", - ["6400"]="JET-VAC", - ["6700"]="FLASHWING", - ["7000"]="TREE REX", - ["7100"]="LIGHTCORE SHROOMBOOM", - ["1C00"]="DARK SPYRO", - ["0600"]="DINORANG" , - ["1200"]="DOUBLE TROUBLE" , - ["1500"]="DRILLSERGEANT" , - ["1400"]="DROBOT", - ["0900"]="LIGHTCORE ERUPTOR" , - ["0B00"]="FLAMESLINGER" , - ["1F00"]="GHOST ROASTER", - ["0E00"]="GILL GRUNT" , - ["1D00"]="HEX", - ["0A00"]="IGNITOR", - ["0300"]="LIGHTNINGROD", - ["0700"]="LIGHTCORE PRISM BREAK", - ["1500"]="SLAMBAM", + ["0000"]="WHIRLWIND", ["0100"]="SONIC BOOM", + ["0200"]="WARNADO", + ["0300"]="LIGHTNINGROD", + ["0400"]="BASH", + ["0500"]="TERRAFIN", + ["0600"]="DINORANG" , + ["0700"]="LIGHTCORE PRISM BREAK", + ["0800"]="SUNBURN", + ["0900"]="LIGHTCORE ERUPTOR", + ["0A00"]="IGNITOR", + ["0B00"]="FLAMESLINGER", + ["0C00"]="ZAP", + ["0D00"]="WHAM SHELL", + ["0E00"]="GILL GRUNT", + ["0F00"]="SLAMBAM", ["1000"]="SPYRO", + ["1100"]="VOODOOD", + ["1200"]="DOUBLE TROUBLE", + ["1300"]="TRIGGER HAPPY", + ["1400"]="DROBOT", + ["1500"]="DRILLSERGEANT", + ["1600"]="BOOMER", + ["1700"]="WRECKING BALL", + ["1800"]="CAMO", + ["1900"]="ZOOK", ["1A00"]="STEALTH ELF", ["1B00"]="STUMP SMASH", - ["0800"]="SUNBURN", - ["0500"]="TERRAFIN", - ["1300"]="TRIGGER HAPPY", - ["1100"]="VOODOOD", - ["0200"]="WARNADO", - ["0D00"]="WHAM SHELL", - ["0000"]="WHIRLWIND", - ["1700"]="WRECKING BALL", - ["0C00"]="ZAP", - ["1900"]="ZOOK", - ["0300"]="DRAGON", - ["012D"]="ICE", - ["012E"]="PIRATE", - ["0130"]="PVPUNLOCK", - ["012F"]="UNDEAD", - ["0200"]="ANVIL" , + ["1D00"]="HEX", + ["1C00"]="DARK SPYRO", + ["1E00"]="CHOPCHOP", + ["1F00"]="GHOST ROASTER", + ["2000"]="CYNDER", + --[[ + GIANTS + --]] + ["6400"]="GIANT JET-VAC", + ["6500"]="GIANT SWARM", + ["6600"]="GIANT CRUSHER", + ["6700"]="GIANT FLASHWING", + ["6800"]="GIANT HOTHEAD", + ["6900"]="GIANT HOTDOG", + ["6A00"]="GIANT CHILL", + ["6B00"]="GIANT THUMPBACK", + ["6C00"]="GIANT POPFIZZ", + ["6D00"]="GIANT NINJINI", + ["6E00"]="GIANT BOUNCER", + ["6F00"]="GIANT SPROCKET", + ["7000"]="GIANT TREE REX", + ["7100"]="LIGHTCORE SHROOMBOOM", + ["7200"]="GIANT EYEBROAWL", + ["7300"]="GIANT FRIGHTRIDER", + + --[[ + ITEM + --]] + ["C800"]="ANVIL", + ["C900"]="SECRET STASH", + ["CA00"]="REGENERATION", + ["CD00"]="SHIELD", ["CB00"]="CROSSED SWORDS", ["CC00"]="HOURGLASS", - ["CA00"]="REGENERATION", - ["C900"]="SECRET STASH", - ["CD00"]="SHIELD", - ["CF00"]="SPARX", ["CE00"]="SPEED BOOTS", + ["CF00"]="SPARX", + ["D000"]="CANNON", + ["D100"]="SCORPIONSTRIKER", + + --[[ + ITEM TRAPS + --]] + ["D200"]="MAGIC TRAP", + ["D300"]="WATER TRAP", + ["D400"]="AIR TRAP", + ["D600"]="TECH TRAP", + ["D700"]="FIRE TRAP", + ["D800"]="EARTH TRAP", + ["D900"]="LIFE TRAP", + ["DA00"]="DARK TRAP", + ["DB00"]="LIGHT TRAP", + ["DC00"]="KAOS TRAP", + + --[[ + ITEM + --]] + ["E600"]="HAND OF FATE", + ["E700"]="PIGGYBANK", + ["E800"]="ROCKET RAM", + ["E900"]="TIKI SPEAKY", + + + --[[ + EXPANSION + --]] + ["012C"]="DRAGON", + ["012D"]="ICE", + ["012E"]="PIRATE", + ["012F"]="UNDEAD", + ["0130"]="PVPUNLOCK", + ["0131"]="MIRROR OF MYSTERY", + ["0132"]="NIGHTMARE EXPRESS", + ["0133"]="SUNSCRAPER SPIRE", + ["0134"]="MIDNIGHT MUSEUM", + + --[[ + LEGENDARY + --]] ["0194"]="LEGENDARY BASH", - ["0430"]="LEGENDARY CHOPCHOP", ["01A0"]="LEGENDARY SPYRO", ["01A3"]="LEGENDARY TRIGGER HAPPY", - ["0202"]="PET GILL GRUNT", - ["020E"]="PET STEALTH ELF", + ["01AE"]="LEGENDARY CHOPCHOP", + + --[[ + TRAPTEAM + --]] + ["01C2"]="TRAPTEAM GUSTO", + ["01C3"]="TRAPTEAM THUNDERBOLT", + ["01C4"]="TRAPTEAM FLINGKONG", + ["01C5"]="TRAPTEAM BLADES", + ["01C6"]="TRAPTEAM WALLOP", + ["01C7"]="TRAPTEAM HEADRUSH", + ["01C8"]="TRAPTEAM FISTBUMP", + ["01C9"]="TRAPTEAM ROCKYROLL", + ["01CA"]="TRAPTEAM WILDFIRE", + ["01CB"]="TRAPTEAM KABOOM", + ["01CC"]="TRAPTEAM TRAILBLAZER", + ["01CD"]="TRAPTEAM TORCH", + ["01CE"]="TRAPTEAM SNAPSHOT", + ["01CF"]="TRAPTEAM LOBSTAR", + ["01D0"]="TRAPTEAM FLIPWRECK", + ["01D1"]="TRAPTEAM ECHO", + ["01D2"]="TRAPTEAM BLASTERMIND", + ["01D3"]="TRAPTEAM ENIGMA", + ["01D4"]="TRAPTEAM DEJAVU", + ["01D5"]="TRAPTEAM COBRA CADABRA", + ["01D6"]="TRAPTEAM JAWBREAKER", + ["01D7"]="TRAPTEAM GEARSHIFT", + ["01D8"]="TRAPTEAM CHOPPER", + ["01D9"]="TRAPTEAM TREADHEAD", + ["01DA"]="TRAPTEAM BUSHWHACK", + ["01DB"]="TRAPTEAM TUFF LUCK", + ["01DC"]="TRAPTEAM FOODFIGHT", + ["01DD"]="TRAPTEAM HIGHFIVE", + ["01DE"]="TRAPTEAM KRYPTKING", + ["01DF"]="TRAPTEAM SHORTCUT", + ["01E0"]="TRAPTEAM BATSPIN", + ["01E1"]="TRAPTEAM FUNNYBONE", + ["01E2"]="TRAPTEAM KNIGHTLIGHT", + ["01E3"]="TRAPTEAM SPOTLIGHT", + ["01E4"]="TRAPTEAM KNIGHTMARE", + ["01E5"]="TRAPTEAM BLACKOUT", + + --[[ + PET + --]] + ["01F6"]="PET BOP", + ["01F7"]="PET SPRY", + ["01F8"]="PET HIJINX", ["01F9"]="PET TERRAFIN", + ["01FA"]="PET BREEZE", + ["01FB"]="PET WEERUPTOR", + ["01FC"]="PET PETVAC", + ["01FD"]="PET SMALLFRY", + ["01FE"]="PET DROBIT", + ["0202"]="PET GILL GRUNT", ["0207"]="PET TRIGGER HAPPY", + ["020E"]="PET STEALTH ELF", + ["021C"]="PET BARKLEY", + ["021D"]="PET THUMPLING", + ["021E"]="PET MINI JINI", + ["021F"]="PET EYE SMALL", + + --[[ + SWAP FORCE + --]] + ["0BB8"]="SWAPFORCE SCRATCH", + ["0BB9"]="SWAPFORCE POPTHORN", + ["0BBA"]="SWAPFORCE SLOBBER TOOTH", + ["0BBB"]="SWAPFORCE SCORP", + ["0BBC"]="SWAPFORCE HOG WILD FRYNO", + ["0BBD"]="SWAPFORCE SMOLDER DASH", + ["0BBE"]="SWAPFORCE BUMBLE BLAST", + ["0BBF"]="SWAPFORCE ZOOLOU", + ["0BC0"]="SWAPFORCE DUNE BUG", + ["0BC1"]="SWAPFORCE STAR STRIKE", + ["0BC2"]="SWAPFORCE COUNTDOWN", + ["0BC3"]="SWAPFORCE WINDUP", + ["0BC4"]="SWAPFORCE ROLLER BRAWL", + ["0BC5"]="SWAPFORCE GRIM CREEPER", + ["0BC6"]="SWAPFORCE RIPTIDE", + ["0BC7"]="SWAPFORCE PUNKSHOCK", } return _names diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index f41fe8aba..dedd3df13 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -253,6 +253,7 @@ local function main(args) local uid = block0:sub(1,8) local itemtype = block1:sub(1,4) local cardid = block1:sub(9,24) + local traptype = block1:sub(25,28) -- Write dump to files if not DEBUG then @@ -264,9 +265,11 @@ local function main(args) -- Show info print( string.rep('--',20) ) - print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) - print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s'):format(cardid ) ) + print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) ) + print( (' Alter ego / traptype : 0x%s'):format(traptype) ) + print( (' UID : 0x%s'):format(uid) ) + print( (' CARDID : 0x%s'):format(cardid ) ) + print( string.rep('--',20) ) end From 5c2b11eb3c094b08b5b31e20e9559ae838c79f73 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 5 Feb 2015 15:43:50 +0100 Subject: [PATCH 10/11] FIX: LF TI WRITE inparameters didn't get copied by sscanf. This removes the "PRIu64" and uses the 012"llx" instead. --- client/cmdlfti.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmdlfti.c b/client/cmdlfti.c index cb5fcd790..12956abd0 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -273,7 +273,8 @@ int CmdTIWrite(const char *Cmd) UsbCommand c = {CMD_WRITE_TI_TYPE}; int res = 0; - res = sscanf(Cmd, "0x%"PRIu64"x 0x%"PRIu64"x 0x%"PRIu64"x ", &c.arg[0], &c.arg[1], &c.arg[2]); + res = sscanf(Cmd, "%012"llx" %012"llx" %012"llx"", &c.arg[0], &c.arg[1], &c.arg[2]); + if (res == 2) c.arg[2]=0; if (res < 2) PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third"); From bb42a03ef1318442fa0e8e2e07c7dbf8bd49fc96 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 5 Feb 2015 19:40:47 +0100 Subject: [PATCH 11/11] Fix #1 for pm3 iclass simulation, remove erroneous extra bit after transmission --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index b1639a88c..b73495a3c 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1534,7 +1534,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe AT91C_BASE_SSC->SSC_THR = SEC_F; // send cycle - for(; i <= respLen; ) { + for(; i < respLen; ) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = resp[i++]; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;