mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge pull request #2173 from wh201906/lf_sniff_clean
Real-time LF sampling
This commit is contained in:
commit
17a93a3b1b
24 changed files with 900 additions and 231 deletions
|
@ -851,13 +851,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_ACQ_RAW_ADC: {
|
||||
struct p {
|
||||
uint32_t samples : 31;
|
||||
bool verbose : 1;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
uint32_t bits = SampleLF(payload->verbose, payload->samples, true);
|
||||
reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits));
|
||||
lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes;
|
||||
if (payload->realtime) {
|
||||
ReadLF_realtime(true);
|
||||
} else {
|
||||
uint32_t bits = SampleLF(payload->verbose, payload->samples, true);
|
||||
reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_LF_MOD_THEN_ACQ_RAW_ADC: {
|
||||
|
@ -880,14 +880,13 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_SNIFF_RAW_ADC: {
|
||||
struct p {
|
||||
uint32_t samples : 31;
|
||||
bool verbose : 1;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *)packet->data.asBytes;
|
||||
|
||||
uint32_t bits = SniffLF(payload->verbose, payload->samples, true);
|
||||
reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits));
|
||||
lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes;
|
||||
if (payload->realtime) {
|
||||
ReadLF_realtime(false);
|
||||
} else {
|
||||
uint32_t bits = SniffLF(payload->verbose, payload->samples, true);
|
||||
reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HID_WATCH: {
|
||||
|
|
|
@ -493,7 +493,7 @@ void FpgaDownloadAndGo(int bitstream_version) {
|
|||
#endif
|
||||
|
||||
// Send waiting time extension request as this will take a while
|
||||
send_wtx(1500);
|
||||
send_wtx(FPGA_LOAD_WAIT_TIME);
|
||||
|
||||
bool verbose = (g_dbglevel > 3);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "lfdemod.h"
|
||||
#include "string.h" // memset
|
||||
#include "appmain.h" // print stack
|
||||
#include "usb_cdc.h" // real-time sampling
|
||||
|
||||
/*
|
||||
Default LF config is set to:
|
||||
|
@ -228,7 +229,7 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool
|
|||
|
||||
// write the current byte
|
||||
data.buffer[data.numbits >> 3] |= sample >> bits_offset;
|
||||
int numbits = data.numbits + bits_cap;
|
||||
uint32_t numbits = data.numbits + bits_cap;
|
||||
|
||||
// write the remaining bits to the next byte
|
||||
data.buffer[numbits >> 3] |= sample << (bits_cap);
|
||||
|
@ -305,7 +306,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
|||
|
||||
// only every 4000th times, in order to save time when collecting samples.
|
||||
// interruptible only when logging not yet triggered
|
||||
if ((checked >= 4000) && trigger_hit == false) {
|
||||
if (trigger_hit == false && (checked >= 4000)) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
|
@ -324,7 +325,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
|||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// Test point 8 (TP8) can be used to trigger oscilloscope
|
||||
// (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
|
||||
if (ledcontrol) LED_D_OFF();
|
||||
|
||||
// threshold either high or low values 128 = center 0. if trigger = 178
|
||||
|
@ -337,10 +338,9 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
|||
}
|
||||
continue;
|
||||
}
|
||||
trigger_hit = true;
|
||||
}
|
||||
|
||||
trigger_hit = true;
|
||||
|
||||
if (samples_to_skip > 0) {
|
||||
samples_to_skip--;
|
||||
continue;
|
||||
|
@ -370,6 +370,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
|
|||
}
|
||||
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
|
||||
|
@ -424,6 +425,123 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol) {
|
|||
BigBuf_Clear_ext(false);
|
||||
return ReadLF(true, verbose, sample_size, ledcontrol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do LF sampling and send samples to the USB
|
||||
*
|
||||
* Uses parameters in config. Only bits_per_sample = 8 is working now
|
||||
*
|
||||
* @param reader_field - true for reading tags, false for sniffing
|
||||
* @return sampling result
|
||||
**/
|
||||
int ReadLF_realtime(bool reader_field) {
|
||||
// parameters from config and constants
|
||||
const uint8_t bits_per_sample = config.bits_per_sample;
|
||||
const int16_t trigger_threshold = config.trigger_threshold;
|
||||
int32_t samples_to_skip = config.samples_to_skip;
|
||||
const uint8_t decimation = config.decimation;
|
||||
|
||||
const int8_t size_threshold_table[9] = {0, 64, 64, 60, 64, 60, 60, 56, 64};
|
||||
const int8_t size_threshold = size_threshold_table[bits_per_sample];
|
||||
|
||||
// DoAcquisition() start
|
||||
uint8_t last_byte = 0;
|
||||
uint8_t curr_byte = 0;
|
||||
int return_value = PM3_SUCCESS;
|
||||
|
||||
uint32_t sample_buffer_len = AT91C_USB_EP_IN_SIZE;
|
||||
initSampleBuffer(&sample_buffer_len);
|
||||
if (sample_buffer_len != AT91C_USB_EP_IN_SIZE) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
bool trigger_hit = false;
|
||||
int16_t checked = 0;
|
||||
|
||||
return_value = async_usb_write_start();
|
||||
if (return_value != PM3_SUCCESS) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
BigBuf_Clear_ext(false);
|
||||
LFSetupFPGAForADC(config.divisor, reader_field);
|
||||
|
||||
while (BUTTON_PRESS() == false) {
|
||||
// only every 4000th times, in order to save time when collecting samples.
|
||||
// interruptible only when logging not yet triggered
|
||||
if (trigger_hit == false && (checked >= 4000)) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY)) {
|
||||
LED_D_ON();
|
||||
}
|
||||
|
||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
|
||||
// (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
|
||||
LED_D_OFF();
|
||||
|
||||
// threshold either high or low values 128 = center 0. if trigger = 178
|
||||
if (trigger_hit == false) {
|
||||
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
|
||||
continue;
|
||||
}
|
||||
trigger_hit = true;
|
||||
}
|
||||
|
||||
if (samples_to_skip > 0) {
|
||||
samples_to_skip--;
|
||||
continue;
|
||||
}
|
||||
|
||||
logSample(sample, decimation, bits_per_sample, false);
|
||||
|
||||
// Write to USB FIFO if byte changed
|
||||
curr_byte = data.numbits >> 3;
|
||||
if (curr_byte > last_byte) {
|
||||
async_usb_write_pushByte(data.buffer[last_byte]);
|
||||
}
|
||||
last_byte = curr_byte;
|
||||
|
||||
if (samples.total_saved == size_threshold) {
|
||||
// Request USB transmission and change FIFO bank
|
||||
if (async_usb_write_requestWrite() == false) {
|
||||
return_value = PM3_EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset sample
|
||||
last_byte = 0;
|
||||
data.numbits = 0;
|
||||
samples.counter = size_threshold;
|
||||
samples.total_saved = 0;
|
||||
|
||||
} else if (samples.total_saved == 1) {
|
||||
// Check if there is any data from client
|
||||
if (data_available_fast()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LED_D_OFF();
|
||||
return_value = async_usb_write_stop();
|
||||
|
||||
// DoAcquisition() end
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
return return_value;
|
||||
}
|
||||
/**
|
||||
* Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
|
|
|
@ -51,6 +51,16 @@ void doT55x7Acquisition(size_t sample_size, bool ledcontrol);
|
|||
**/
|
||||
uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol);
|
||||
|
||||
/**
|
||||
* Do LF sampling and send samples to the USB
|
||||
*
|
||||
* Uses parameters in config. Only bits_per_sample = 8 is working now
|
||||
*
|
||||
* @param reader_field - true for reading tags, false for sniffing
|
||||
* @return sampling result
|
||||
**/
|
||||
int ReadLF_realtime(bool reader_field);
|
||||
|
||||
/**
|
||||
* Initializes the FPGA for sniff-mode (field off), and acquires the samples.
|
||||
* @return number of bits sampled
|
||||
|
|
|
@ -153,7 +153,7 @@ static void zx_get(bool ledcontrol) {
|
|||
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
(void)sample;
|
||||
|
||||
// Test point 8 (TP8) can be used to trigger oscilloscope
|
||||
// (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
|
||||
if (ledcontrol) LED_D_OFF();
|
||||
|
||||
}
|
||||
|
|
|
@ -298,6 +298,8 @@ int BUTTON_HELD(int ms) {
|
|||
return BUTTON_ERROR;
|
||||
}
|
||||
|
||||
// This function returns false if no data is available or
|
||||
// the USB connection is invalid.
|
||||
bool data_available(void) {
|
||||
#ifdef WITH_FPC_USART_HOST
|
||||
return usb_poll_validate_length() || (usart_rxdata_available() > 0);
|
||||
|
@ -305,3 +307,14 @@ bool data_available(void) {
|
|||
return usb_poll_validate_length();
|
||||
#endif
|
||||
}
|
||||
|
||||
// This function doesn't check if the USB connection is valid.
|
||||
// In most of the cases, you should use data_available() unless
|
||||
// the timing is critical.
|
||||
bool data_available_fast(void) {
|
||||
#ifdef WITH_FPC_USART_HOST
|
||||
return usb_available_length() || (usart_rxdata_available() > 0);
|
||||
#else
|
||||
return usb_available_length();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -101,5 +101,6 @@ void SpinUp(uint32_t speed);
|
|||
int BUTTON_CLICKED(int ms);
|
||||
int BUTTON_HELD(int ms);
|
||||
bool data_available(void);
|
||||
bool data_available_fast(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -564,7 +564,11 @@ static int Cmdmandecoderaw(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t bits[MAX_DEMOD_BUF_LEN] = {0};
|
||||
uint8_t *bits = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// make sure its just binary data 0|1|7 in buffer
|
||||
int high = 0, low = 0;
|
||||
|
@ -579,6 +583,7 @@ static int Cmdmandecoderaw(const char *Cmd) {
|
|||
|
||||
if (high > 7 || low < 0) {
|
||||
PrintAndLogEx(ERR, "Error: please first raw demod then manchester raw decode");
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -587,6 +592,7 @@ static int Cmdmandecoderaw(const char *Cmd) {
|
|||
uint16_t err_cnt = manrawdecode(bits, &size, invert, &offset);
|
||||
if (err_cnt > max_err) {
|
||||
PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt);
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -611,6 +617,7 @@ static int Cmdmandecoderaw(const char *Cmd) {
|
|||
}
|
||||
setDemodBuff(bits, size, 0);
|
||||
setClockGrid(g_DemodClock * 2, g_DemodStartIdx);
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -651,17 +658,27 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t bits[MAX_DEMOD_BUF_LEN] = {0};
|
||||
size_t size = sizeof(bits);
|
||||
if (!getDemodBuff(bits, &size)) return PM3_ESOFT;
|
||||
uint8_t *bits = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t size = MAX_DEMOD_BUF_LEN;
|
||||
if (!getDemodBuff(bits, &size)) {
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
int err_cnt = BiphaseRawDecode(bits, &size, &offset, invert);
|
||||
if (err_cnt < 0) {
|
||||
PrintAndLogEx(ERR, "Error during decode " _RED_("%i"), err_cnt);
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (err_cnt > max_err) {
|
||||
PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt);
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -674,6 +691,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) {
|
|||
|
||||
setDemodBuff(bits, size, 0);
|
||||
setClockGrid(g_DemodClock * 2, g_DemodStartIdx + g_DemodClock * offset);
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -681,10 +699,16 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) {
|
|||
int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
||||
//ask raw demod g_GraphBuffer first
|
||||
|
||||
uint8_t bs[MAX_DEMOD_BUF_LEN];
|
||||
size_t size = getFromGraphBuf(bs);
|
||||
uint8_t *bs = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t));
|
||||
if (bs == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t size = getFromGraphBufEx(bs, MAX_DEMOD_BUF_LEN);
|
||||
if (size == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf");
|
||||
free(bs);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
int startIdx = 0;
|
||||
|
@ -692,6 +716,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
|||
int errCnt = askdemod_ext(bs, &size, &clk, &invert, maxErr, 0, 0, &startIdx);
|
||||
if (errCnt < 0 || errCnt > maxErr) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk);
|
||||
free(bs);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -699,10 +724,12 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
|||
errCnt = BiphaseRawDecode(bs, &size, &offset, invert);
|
||||
if (errCnt < 0) {
|
||||
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt);
|
||||
free(bs);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
if (errCnt > maxErr) {
|
||||
if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt);
|
||||
free(bs);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -716,6 +743,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2));
|
||||
printDemodBuff(offset, false, false, false);
|
||||
}
|
||||
free(bs);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1039,11 @@ static int CmdUndecimate(const char *Cmd) {
|
|||
CLIParserFree(ctx);
|
||||
|
||||
//We have memory, don't we?
|
||||
int swap[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
int *swap = calloc(MAX_GRAPH_TRACE_LEN, sizeof(int));
|
||||
if (swap == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
uint32_t g_index = 0, s_index = 0;
|
||||
while (g_index < g_GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) {
|
||||
int count = 0;
|
||||
|
@ -1028,6 +1060,7 @@ static int CmdUndecimate(const char *Cmd) {
|
|||
memcpy(g_GraphBuffer, swap, s_index * sizeof(int));
|
||||
g_GraphTraceLen = s_index;
|
||||
RepaintGraphWindow();
|
||||
free(swap);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1707,7 +1740,11 @@ int CmdHpf(const char *Cmd) {
|
|||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
removeSignalOffset(bits, size);
|
||||
// push it back to graph
|
||||
|
@ -1716,6 +1753,7 @@ int CmdHpf(const char *Cmd) {
|
|||
computeSignalProperties(bits, size);
|
||||
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1776,35 +1814,48 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_conf
|
|||
bits_per_sample = sc->bits_per_sample;
|
||||
}
|
||||
|
||||
return getSamplesFromBufEx(got, n, bits_per_sample, verbose);;
|
||||
}
|
||||
|
||||
int getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_sample, bool verbose) {
|
||||
|
||||
size_t max_num = MIN(sample_num, MAX_GRAPH_TRACE_LEN);
|
||||
|
||||
if (bits_per_sample < 8) {
|
||||
|
||||
if (verbose) PrintAndLogEx(INFO, "Unpacking...");
|
||||
|
||||
BitstreamOut_t bout = { got, bits_per_sample * n, 0};
|
||||
uint32_t j = 0;
|
||||
for (j = 0; j * bits_per_sample < n * 8 && j * bits_per_sample < MAX_GRAPH_TRACE_LEN * 8; j++) {
|
||||
BitstreamOut_t bout = {data, bits_per_sample * sample_num, 0};
|
||||
size_t j = 0;
|
||||
for (j = 0; j < max_num; j++) {
|
||||
uint8_t sample = getByte(bits_per_sample, &bout);
|
||||
g_GraphBuffer[j] = ((int) sample) - 127;
|
||||
}
|
||||
g_GraphTraceLen = j;
|
||||
|
||||
if (verbose) PrintAndLogEx(INFO, "Unpacked %d samples", j);
|
||||
if (verbose) PrintAndLogEx(INFO, "Unpacked %zu samples", j);
|
||||
|
||||
} else {
|
||||
for (uint32_t j = 0; j < n; j++) {
|
||||
g_GraphBuffer[j] = ((int)got[j]) - 127;
|
||||
for (size_t j = 0; j < max_num; j++) {
|
||||
g_GraphBuffer[j] = ((int)data[j]) - 127;
|
||||
}
|
||||
g_GraphTraceLen = n;
|
||||
g_GraphTraceLen = max_num;
|
||||
}
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noise detection
|
||||
computeSignalProperties(bits, size);
|
||||
free(bits);
|
||||
|
||||
setClockGrid(0, 0);
|
||||
g_DemodBufferLen = 0;
|
||||
RepaintGraphWindow();
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2094,12 +2145,17 @@ static int CmdLoad(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " samples", g_GraphTraceLen);
|
||||
|
||||
if (nofix == false) {
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
|
||||
removeSignalOffset(bits, size);
|
||||
setGraphBuf(bits, size);
|
||||
computeSignalProperties(bits, size);
|
||||
free(bits);
|
||||
}
|
||||
|
||||
setClockGrid(0, 0);
|
||||
|
@ -2231,12 +2287,17 @@ int CmdNorm(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noise detection
|
||||
computeSignalProperties(bits, size);
|
||||
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2377,12 +2438,17 @@ static int CmdDirectionalThreshold(const char *Cmd) {
|
|||
directionalThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down);
|
||||
|
||||
// set signal properties low/high/mean/amplitude and isnoice detection
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noice detection
|
||||
computeSignalProperties(bits, size);
|
||||
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2420,11 +2486,16 @@ static int CmdZerocrossings(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noise detection
|
||||
computeSignalProperties(bits, size);
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2733,11 +2804,16 @@ static int CmdDataIIR(const char *Cmd) {
|
|||
|
||||
iceSimple_Filter(g_GraphBuffer, g_GraphTraceLen, k);
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noise detection
|
||||
computeSignalProperties(bits, size);
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3360,11 +3436,16 @@ static int CmdCenterThreshold(const char *Cmd) {
|
|||
centerThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down);
|
||||
|
||||
// set signal properties low/high/mean/amplitude and isnoice detection
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noice detection
|
||||
computeSignalProperties(bits, size);
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3405,11 +3486,16 @@ static int CmdEnvelope(const char *Cmd) {
|
|||
|
||||
envelope_square(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen);
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
// set signal properties low/high/mean/amplitude and is_noice detection
|
||||
computeSignalProperties(bits, size);
|
||||
RepaintGraphWindow();
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3584,4 +3670,3 @@ int CmdData(const char *Cmd) {
|
|||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG
|
|||
|
||||
int getSamples(uint32_t n, bool verbose);
|
||||
int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_config);
|
||||
int getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_sample, bool verbose);
|
||||
|
||||
void setClockGrid(uint32_t clk, int offset);
|
||||
int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down);
|
||||
|
|
|
@ -66,8 +66,6 @@
|
|||
#include "crc.h"
|
||||
#include "pm3_cmd.h" // for LF_CMDREAD_MAX_EXTRA_SYMBOLS
|
||||
|
||||
static bool gs_lf_threshold_set = false;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
// Informative user function.
|
||||
|
@ -433,7 +431,11 @@ int CmdFlexdemod(const char *Cmd) {
|
|||
#endif
|
||||
int i, j, start, bit, sum;
|
||||
|
||||
int data[g_GraphTraceLen];
|
||||
int *data = calloc(g_GraphTraceLen, sizeof(int));
|
||||
if (data == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
memcpy(data, g_GraphBuffer, g_GraphTraceLen);
|
||||
|
||||
size_t size = g_GraphTraceLen;
|
||||
|
@ -454,6 +456,7 @@ int CmdFlexdemod(const char *Cmd) {
|
|||
|
||||
if (start == size - LONG_WAIT) {
|
||||
PrintAndLogEx(WARNING, "nothing to wait for");
|
||||
free(data);
|
||||
return PM3_ENODATA;
|
||||
}
|
||||
|
||||
|
@ -497,6 +500,7 @@ int CmdFlexdemod(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
RepaintGraphWindow();
|
||||
free(data);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -644,7 +648,6 @@ int CmdLFConfig(const char *Cmd) {
|
|||
config.divisor = LF_DIVISOR_125;
|
||||
config.samples_to_skip = 0;
|
||||
config.trigger_threshold = 0;
|
||||
gs_lf_threshold_set = false;
|
||||
}
|
||||
|
||||
if (use_125)
|
||||
|
@ -689,44 +692,83 @@ int CmdLFConfig(const char *Cmd) {
|
|||
|
||||
if (trigg > -1) {
|
||||
config.trigger_threshold = trigg;
|
||||
gs_lf_threshold_set = (config.trigger_threshold > 0);
|
||||
}
|
||||
|
||||
config.samples_to_skip = skip;
|
||||
return lf_config(&config);
|
||||
}
|
||||
|
||||
int lf_read(bool verbose, uint32_t samples) {
|
||||
static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) {
|
||||
if (!g_session.pm3_present) return PM3_ENOTTY;
|
||||
|
||||
struct p {
|
||||
uint32_t samples : 31;
|
||||
bool verbose : 1;
|
||||
} PACKED;
|
||||
|
||||
struct p payload;
|
||||
lf_sample_payload_t payload = {0};
|
||||
payload.realtime = realtime;
|
||||
payload.verbose = verbose;
|
||||
payload.samples = samples;
|
||||
|
||||
sample_config current_config;
|
||||
int retval = lf_getconfig(¤t_config);
|
||||
if (retval != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "failed to get current device config");
|
||||
return retval;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (gs_lf_threshold_set) {
|
||||
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
|
||||
} else {
|
||||
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
const uint8_t bits_per_sample = current_config.bits_per_sample;
|
||||
const bool is_trigger_threshold_set = (current_config.trigger_threshold > 0);
|
||||
|
||||
if (realtime) {
|
||||
uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t));
|
||||
if (realtimeBuf == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t sample_bytes = samples * bits_per_sample;
|
||||
sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0);
|
||||
|
||||
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
if (is_trigger_threshold_set) {
|
||||
size_t first_receive_len = 32; // larger than the response of CMD_WTX
|
||||
// Wait until a bunch of data arrives
|
||||
first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false);
|
||||
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true);
|
||||
sample_bytes += first_receive_len;
|
||||
} else {
|
||||
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true);
|
||||
}
|
||||
samples = sample_bytes * 8 / bits_per_sample;
|
||||
PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes);
|
||||
if (samples != 0) {
|
||||
getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose);
|
||||
}
|
||||
|
||||
free(realtimeBuf);
|
||||
} else {
|
||||
payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples;
|
||||
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (is_trigger_threshold_set) {
|
||||
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
|
||||
} else {
|
||||
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
// response is number of bits read
|
||||
uint32_t size = (resp.data.asDwords[0] / bits_per_sample);
|
||||
getSamples(size, verbose);
|
||||
}
|
||||
|
||||
// response is number of bits read
|
||||
uint32_t size = (resp.data.asDwords[0] / 8);
|
||||
getSamples(size, verbose);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int lf_read(bool verbose, uint64_t samples) {
|
||||
return lf_read_internal(false, verbose, samples);
|
||||
}
|
||||
|
||||
int CmdLFRead(const char *Cmd) {
|
||||
// In real-time mode, the first few bytes might be the response of CMD_WTX
|
||||
// rather than the real samples if the LF FPGA image is not ready.
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf read",
|
||||
"Sniff low frequency signal.\n"
|
||||
|
@ -734,6 +776,7 @@ int CmdLFRead(const char *Cmd) {
|
|||
_CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at it"),
|
||||
"lf read -v -s 12000 --> collect 12000 samples\n"
|
||||
"lf read -s 3000 -@ --> oscilloscope style \n"
|
||||
"lf read -r --> use real-time mode \n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
@ -741,57 +784,100 @@ int CmdLFRead(const char *Cmd) {
|
|||
arg_u64_0("s", "samples", "<dec>", "number of samples to collect"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_lit0("@", NULL, "continuous reading mode"),
|
||||
arg_lit0("r", "realtime", "real-time reading mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
uint32_t samples = arg_get_u32_def(ctx, 1, 0);
|
||||
uint64_t samples = arg_get_u64_def(ctx, 1, 0);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
bool cm = arg_get_lit(ctx, 3);
|
||||
bool realtime = arg_get_lit(ctx, 4);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (g_session.pm3_present == false)
|
||||
return PM3_ENOTTY;
|
||||
|
||||
if (cm) {
|
||||
if (realtime && samples == 0) {
|
||||
samples = MAX_GRAPH_TRACE_LEN;
|
||||
}
|
||||
|
||||
if (cm || realtime) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
}
|
||||
int ret = PM3_SUCCESS;
|
||||
do {
|
||||
ret = lf_read(verbose, samples);
|
||||
ret = lf_read_internal(realtime, verbose, samples);
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lf_sniff(bool verbose, uint32_t samples) {
|
||||
int lf_sniff(bool realtime, bool verbose, uint64_t samples) {
|
||||
if (!g_session.pm3_present) return PM3_ENOTTY;
|
||||
|
||||
struct p {
|
||||
uint32_t samples : 31;
|
||||
bool verbose : 1;
|
||||
} PACKED payload;
|
||||
|
||||
payload.samples = (samples & 0xFFFF);
|
||||
lf_sample_payload_t payload = {0};
|
||||
payload.realtime = realtime;
|
||||
payload.verbose = verbose;
|
||||
|
||||
sample_config current_config;
|
||||
int retval = lf_getconfig(¤t_config);
|
||||
if (retval != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "failed to get current device config");
|
||||
return retval;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (gs_lf_threshold_set) {
|
||||
WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp);
|
||||
} else {
|
||||
if (WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
const uint8_t bits_per_sample = current_config.bits_per_sample;
|
||||
const bool is_trigger_threshold_set = (current_config.trigger_threshold > 0);
|
||||
|
||||
if (realtime) {
|
||||
uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t));
|
||||
if (realtimeBuf == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t sample_bytes = samples * bits_per_sample;
|
||||
sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0);
|
||||
|
||||
SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
if (is_trigger_threshold_set) {
|
||||
size_t first_receive_len = 32; // larger than the response of CMD_WTX
|
||||
// Wait until a bunch of data arrives
|
||||
first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false);
|
||||
sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true);
|
||||
sample_bytes += first_receive_len;
|
||||
} else {
|
||||
sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true);
|
||||
}
|
||||
samples = sample_bytes * 8 / bits_per_sample;
|
||||
PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes);
|
||||
if (samples != 0) {
|
||||
getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose);
|
||||
}
|
||||
|
||||
free(realtimeBuf);
|
||||
} else {
|
||||
payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples;
|
||||
SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (is_trigger_threshold_set) {
|
||||
WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp);
|
||||
} else {
|
||||
if (WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500) == false) {
|
||||
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
// response is number of bits read
|
||||
uint32_t size = (resp.data.asDwords[0] / bits_per_sample);
|
||||
getSamples(size, verbose);
|
||||
}
|
||||
|
||||
// response is number of bits read
|
||||
uint32_t size = (resp.data.asDwords[0] / 8);
|
||||
getSamples(size, verbose);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int CmdLFSniff(const char *Cmd) {
|
||||
// In real-time mode, the first few bytes might be the response of CMD_WTX
|
||||
// rather than the real samples if the LF FPGA image is not ready.
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "lf sniff",
|
||||
"Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n"
|
||||
|
@ -802,6 +888,7 @@ int CmdLFSniff(const char *Cmd) {
|
|||
_CYAN_(" - use ") _YELLOW_("`lf search -1`") _CYAN_(" to see if signal can be automatic decoded\n"),
|
||||
"lf sniff -v\n"
|
||||
"lf sniff -s 3000 -@ --> oscilloscope style \n"
|
||||
"lf sniff -r --> use real-time mode \n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
|
@ -809,24 +896,30 @@ int CmdLFSniff(const char *Cmd) {
|
|||
arg_u64_0("s", "samples", "<dec>", "number of samples to collect"),
|
||||
arg_lit0("v", "verbose", "verbose output"),
|
||||
arg_lit0("@", NULL, "continuous sniffing mode"),
|
||||
arg_lit0("r", "realtime", "real-time sniffing mode"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
uint32_t samples = (arg_get_u32_def(ctx, 1, 0) & 0xFFFF);
|
||||
uint64_t samples = arg_get_u64_def(ctx, 1, 0);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
bool cm = arg_get_lit(ctx, 3);
|
||||
bool realtime = arg_get_lit(ctx, 4);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (g_session.pm3_present == false)
|
||||
return PM3_ENOTTY;
|
||||
|
||||
if (cm) {
|
||||
if (realtime && samples == 0) {
|
||||
samples = MAX_GRAPH_TRACE_LEN;
|
||||
}
|
||||
|
||||
if (cm || realtime) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
}
|
||||
int ret = PM3_SUCCESS;
|
||||
do {
|
||||
ret = lf_sniff(verbose, samples);
|
||||
} while (cm && !kbd_enter_pressed());
|
||||
ret = lf_sniff(realtime, verbose, samples);
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ int CmdLFSniff(const char *Cmd);
|
|||
int CmdVchDemod(const char *Cmd);
|
||||
int CmdLFfind(const char *Cmd);
|
||||
|
||||
int lf_read(bool verbose, uint32_t samples);
|
||||
int lf_sniff(bool verbose, uint32_t samples);
|
||||
int lf_read(bool verbose, uint64_t samples);
|
||||
int lf_sniff(bool realtime, bool verbose, uint64_t samples);
|
||||
int lf_config(sample_config *config);
|
||||
int lf_getconfig(sample_config *config);
|
||||
int lfsim_upload_gb(void);
|
||||
|
|
|
@ -117,10 +117,15 @@ int demodHID(bool verbose) {
|
|||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint32_t hi2 = 0, hi = 0, lo = 0;
|
||||
|
||||
uint8_t bits[g_GraphTraceLen];
|
||||
uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
if (size == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples"));
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
//get binary from fsk wave
|
||||
|
@ -141,11 +146,13 @@ int demodHID(bool verbose) {
|
|||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx);
|
||||
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
setDemodBuff(bits, size, idx);
|
||||
setClockGrid(50, waveIdx + (idx * 50));
|
||||
free(bits);
|
||||
|
||||
if (hi2 == 0 && hi == 0 && lo == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found"));
|
||||
|
|
|
@ -403,7 +403,11 @@ static int CmdIndalaDemodAlt(const char *Cmd) {
|
|||
|
||||
// worst case with g_GraphTraceLen=40000 is < 4096
|
||||
// under normal conditions it's < 2048
|
||||
uint8_t data[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
uint8_t *data = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (data == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t datasize = getFromGraphBuf(data);
|
||||
|
||||
uint8_t rawbits[4096] = {0};
|
||||
|
@ -446,6 +450,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) {
|
|||
count = 0;
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
if (rawbit > 0) {
|
||||
PrintAndLogEx(INFO, "Recovered %d raw bits, expected: %zu", rawbit, g_GraphTraceLen / 32);
|
||||
|
|
|
@ -66,10 +66,15 @@ static int CmdIOProxWatch(const char *Cmd) {
|
|||
int demodIOProx(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
int idx = 0, retval = PM3_SUCCESS;
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
if (size < 65) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer");
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
//get binary from fsk wave
|
||||
|
@ -93,6 +98,7 @@ int demodIOProx(bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error demoding fsk %d", idx);
|
||||
}
|
||||
}
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
setDemodBuff(bits, size, idx);
|
||||
|
@ -103,6 +109,7 @@ int demodIOProx(bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox data not found - FSK Bits: %zu", size);
|
||||
if (size > 92) PrintAndLogEx(DEBUG, "%s", sprint_bytebits_bin_break(bits, 92, 16));
|
||||
}
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -156,6 +163,7 @@ int demodIOProx(bool verbose) {
|
|||
printDemodBuff(0, false, false, true);
|
||||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
free(bits);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -441,4 +449,3 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) {
|
|||
PrintAndLogEx(SUCCESS, "IO raw bits:\n %s \n", sprint_bytebits_bin(bits, 64));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,10 +103,15 @@ static uint8_t GetParadoxBits(const uint32_t fc, const uint32_t cn, unsigned int
|
|||
int demodParadox(bool verbose, bool oldChksum) {
|
||||
(void) verbose; // unused so far
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
if (size == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples");
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -125,6 +130,7 @@ int demodParadox(bool verbose, bool oldChksum) {
|
|||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error demoding fsk %d", idx);
|
||||
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -175,6 +181,7 @@ int demodParadox(bool verbose, bool oldChksum) {
|
|||
|
||||
if (hi2 == 0 && hi == 0 && lo == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found");
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -230,6 +237,7 @@ int demodParadox(bool verbose, bool oldChksum) {
|
|||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -500,5 +508,3 @@ int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx) {
|
|||
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -43,10 +43,15 @@ static int CmdHelp(const char *Cmd);
|
|||
int demodPyramid(bool verbose) {
|
||||
(void) verbose; // unused so far
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
|
||||
if (bits == NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
size_t size = getFromGraphBuf(bits);
|
||||
if (size == 0) {
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid not enough samples");
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
//get binary from fsk wave
|
||||
|
@ -65,6 +70,7 @@ int demodPyramid(bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: size not correct: %zu", size);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: error demoding fsk idx: %d", idx);
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
setDemodBuff(bits, size, idx);
|
||||
|
@ -113,6 +119,7 @@ int demodPyramid(bool verbose) {
|
|||
PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: parity check failed - IDX: %d, hi3: %08X", idx, rawHi3);
|
||||
else
|
||||
PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: at parity check - tag size does not match Pyramid format, SIZE: %zu, IDX: %d, hi3: %08X", size, idx, rawHi3);
|
||||
free(bits);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
|
@ -181,6 +188,7 @@ int demodPyramid(bool verbose) {
|
|||
printDemodBuff(0, false, false, false);
|
||||
}
|
||||
|
||||
free(bits);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -507,4 +515,3 @@ int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) {
|
|||
|
||||
return (int)startIdx;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ capabilities_t g_pm3_capabilities;
|
|||
|
||||
static pthread_t communication_thread;
|
||||
static bool comm_thread_dead = false;
|
||||
static bool comm_raw_mode = false;
|
||||
static uint8_t *comm_raw_data = NULL;
|
||||
static size_t comm_raw_len = 0;
|
||||
static size_t comm_raw_pos = 0;
|
||||
|
||||
// Transmit buffer.
|
||||
static PacketCommandOLD txBuffer;
|
||||
|
@ -346,6 +350,8 @@ __attribute__((force_align_arg_pointer))
|
|||
bool commfailed = false;
|
||||
PacketResponseNG rx;
|
||||
PacketResponseNGRaw rx_raw;
|
||||
// Stash the last state of is_receiving_raw, to detect if state changed
|
||||
bool is_receiving_raw_last = false;
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
disableAppNap("Proxmark3 polling UART");
|
||||
|
@ -368,136 +374,175 @@ __attribute__((force_align_arg_pointer))
|
|||
break;
|
||||
}
|
||||
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen);
|
||||
bool is_receiving_raw = __atomic_load_n(&comm_raw_mode, __ATOMIC_SEQ_CST);
|
||||
|
||||
if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) {
|
||||
rx.magic = rx_raw.pre.magic;
|
||||
uint16_t length = rx_raw.pre.length;
|
||||
rx.ng = rx_raw.pre.ng;
|
||||
rx.status = rx_raw.pre.status;
|
||||
rx.cmd = rx_raw.pre.cmd;
|
||||
if (rx.magic == RESPONSENG_PREAMBLE_MAGIC) { // New style NG reply
|
||||
if (length > PM3_CMD_DATA_SIZE) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with incompatible length: 0x%04x", length);
|
||||
if (is_receiving_raw) {
|
||||
uint8_t *bufferData = __atomic_load_n(&comm_raw_data, __ATOMIC_SEQ_CST); // read only
|
||||
size_t bufferLen = __atomic_load_n(&comm_raw_len, __ATOMIC_SEQ_CST); // read only
|
||||
size_t bufferPos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); // read and write
|
||||
if (bufferPos < bufferLen) {
|
||||
size_t rxMaxLen = bufferLen - bufferPos;
|
||||
|
||||
rxMaxLen = MIN(COMM_RAW_RECEIVE_LEN, rxMaxLen);
|
||||
|
||||
res = uart_receive(sp, bufferData + bufferPos, rxMaxLen, &rxlen);
|
||||
if (res == PM3_SUCCESS) {
|
||||
uint64_t clk = msclock();
|
||||
__atomic_store_n(&timeout_start_time, clk, __ATOMIC_SEQ_CST);
|
||||
__atomic_store_n(&comm_raw_pos, bufferPos + rxlen, __ATOMIC_SEQ_CST);
|
||||
} else if (res != PM3_ENODATA) {
|
||||
PrintAndLogEx(WARNING, "Error when reading raw data: %zu/%zu, %d", bufferPos, bufferLen, res);
|
||||
error = true;
|
||||
if (res == PM3_ENOTTY) {
|
||||
commfailed = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ignore data when bufferPos >= bufferLen and is_receiving_raw has not been set to false
|
||||
uint8_t dummyData[64];
|
||||
uint32_t dummyLen;
|
||||
uart_receive(sp, dummyData, sizeof(dummyData), &dummyLen);
|
||||
}
|
||||
} else {
|
||||
if (is_receiving_raw_last) {
|
||||
// is_receiving_raw changed from true to false
|
||||
|
||||
if ((!error) && (length > 0)) { // Get the variable length payload
|
||||
// Set the buffer as undefined
|
||||
// comm_raw_data == NULL is used in SetCommunicationReceiveMode()
|
||||
__atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen);
|
||||
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.data, length, &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != length)) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with variable part too short? %d/%d", rxlen, length);
|
||||
if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) {
|
||||
rx.magic = rx_raw.pre.magic;
|
||||
uint16_t length = rx_raw.pre.length;
|
||||
rx.ng = rx_raw.pre.ng;
|
||||
rx.status = rx_raw.pre.status;
|
||||
rx.cmd = rx_raw.pre.cmd;
|
||||
if (rx.magic == RESPONSENG_PREAMBLE_MAGIC) { // New style NG reply
|
||||
if (length > PM3_CMD_DATA_SIZE) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with incompatible length: 0x%04x", length);
|
||||
error = true;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (rx.ng) { // Received a valid NG frame
|
||||
memcpy(&rx.data, &rx_raw.data, length);
|
||||
rx.length = length;
|
||||
if ((rx.cmd == g_conn.last_command) && (rx.status == PM3_SUCCESS)) {
|
||||
ACK_received = true;
|
||||
}
|
||||
if ((!error) && (length > 0)) { // Get the variable length payload
|
||||
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.data, length, &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != length)) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with variable part too short? %d/%d", rxlen, length);
|
||||
error = true;
|
||||
} else {
|
||||
uint64_t arg[3];
|
||||
if (length < sizeof(arg)) {
|
||||
PrintAndLogEx(WARNING, "Received MIX packet frame with incompatible length: 0x%04x", length);
|
||||
error = true;
|
||||
}
|
||||
if (!error) { // Received a valid MIX frame
|
||||
memcpy(arg, &rx_raw.data, sizeof(arg));
|
||||
rx.oldarg[0] = arg[0];
|
||||
rx.oldarg[1] = arg[1];
|
||||
rx.oldarg[2] = arg[2];
|
||||
memcpy(&rx.data, ((uint8_t *)&rx_raw.data) + sizeof(arg), length - sizeof(arg));
|
||||
rx.length = length - sizeof(arg);
|
||||
if (rx.cmd == CMD_ACK) {
|
||||
|
||||
if (rx.ng) { // Received a valid NG frame
|
||||
memcpy(&rx.data, &rx_raw.data, length);
|
||||
rx.length = length;
|
||||
if ((rx.cmd == g_conn.last_command) && (rx.status == PM3_SUCCESS)) {
|
||||
ACK_received = true;
|
||||
}
|
||||
} else {
|
||||
uint64_t arg[3];
|
||||
if (length < sizeof(arg)) {
|
||||
PrintAndLogEx(WARNING, "Received MIX packet frame with incompatible length: 0x%04x", length);
|
||||
error = true;
|
||||
}
|
||||
if (!error) { // Received a valid MIX frame
|
||||
memcpy(arg, &rx_raw.data, sizeof(arg));
|
||||
rx.oldarg[0] = arg[0];
|
||||
rx.oldarg[1] = arg[1];
|
||||
rx.oldarg[2] = arg[2];
|
||||
memcpy(&rx.data, ((uint8_t *)&rx_raw.data) + sizeof(arg), length - sizeof(arg));
|
||||
rx.length = length - sizeof(arg);
|
||||
if (rx.cmd == CMD_ACK) {
|
||||
ACK_received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((!error) && (length == 0)) { // we received an empty frame
|
||||
if (rx.ng)
|
||||
rx.length = 0; // set received length to 0
|
||||
else { // old frames can't be empty
|
||||
PrintAndLogEx(WARNING, "Received empty MIX packet frame (length: 0x00)");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) { // Get the postamble
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseNGPostamble))) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame without postamble");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) { // Check CRC, accept MAGIC as placeholder
|
||||
rx.crc = rx_raw.foopost.crc;
|
||||
if (rx.crc != RESPONSENG_POSTAMBLE_MAGIC) {
|
||||
uint8_t first, second;
|
||||
compute_crc(CRC_14443_A, (uint8_t *)&rx_raw, sizeof(PacketResponseNGPreamble) + length, &first, &second);
|
||||
if ((first << 8) + second != rx.crc) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with invalid CRC %02X%02X <> %04X", first, second, rx.crc);
|
||||
} else if ((!error) && (length == 0)) { // we received an empty frame
|
||||
if (rx.ng)
|
||||
rx.length = 0; // set received length to 0
|
||||
else { // old frames can't be empty
|
||||
PrintAndLogEx(WARNING, "Received empty MIX packet frame (length: 0x00)");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!error) { // Received a valid OLD frame
|
||||
#ifdef COMMS_DEBUG
|
||||
PrintAndLogEx(NORMAL, "Receiving %s:", rx.ng ? "NG" : "MIX");
|
||||
#endif
|
||||
#ifdef COMMS_DEBUG_RAW
|
||||
print_hex_break((uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), 32);
|
||||
print_hex_break((uint8_t *)&rx_raw.data, rx_raw.pre.length, 32);
|
||||
print_hex_break((uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), 32);
|
||||
#endif
|
||||
PacketResponseReceived(&rx);
|
||||
}
|
||||
} else { // Old style reply
|
||||
PacketResponseOLD rx_old;
|
||||
memcpy(&rx_old, &rx_raw.pre, sizeof(PacketResponseNGPreamble));
|
||||
|
||||
res = uart_receive(sp, ((uint8_t *)&rx_old) + sizeof(PacketResponseNGPreamble), sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble), &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble))) {
|
||||
PrintAndLogEx(WARNING, "Received packet OLD frame with payload too short? %d/%zu", rxlen, sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble));
|
||||
error = true;
|
||||
}
|
||||
if (!error) {
|
||||
if (!error) { // Get the postamble
|
||||
res = uart_receive(sp, (uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseNGPostamble))) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame without postamble");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) { // Check CRC, accept MAGIC as placeholder
|
||||
rx.crc = rx_raw.foopost.crc;
|
||||
if (rx.crc != RESPONSENG_POSTAMBLE_MAGIC) {
|
||||
uint8_t first, second;
|
||||
compute_crc(CRC_14443_A, (uint8_t *)&rx_raw, sizeof(PacketResponseNGPreamble) + length, &first, &second);
|
||||
if ((first << 8) + second != rx.crc) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame with invalid CRC %02X%02X <> %04X", first, second, rx.crc);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!error) { // Received a valid OLD frame
|
||||
#ifdef COMMS_DEBUG
|
||||
PrintAndLogEx(NORMAL, "Receiving OLD:");
|
||||
PrintAndLogEx(NORMAL, "Receiving %s:", rx.ng ? "NG" : "MIX");
|
||||
#endif
|
||||
#ifdef COMMS_DEBUG_RAW
|
||||
print_hex_break((uint8_t *)&rx_old.cmd, sizeof(rx_old.cmd), 32);
|
||||
print_hex_break((uint8_t *)&rx_old.arg, sizeof(rx_old.arg), 32);
|
||||
print_hex_break((uint8_t *)&rx_old.d, sizeof(rx_old.d), 32);
|
||||
print_hex_break((uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), 32);
|
||||
print_hex_break((uint8_t *)&rx_raw.data, rx_raw.pre.length, 32);
|
||||
print_hex_break((uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), 32);
|
||||
#endif
|
||||
rx.ng = false;
|
||||
rx.magic = 0;
|
||||
rx.status = 0;
|
||||
rx.crc = 0;
|
||||
rx.cmd = rx_old.cmd;
|
||||
rx.oldarg[0] = rx_old.arg[0];
|
||||
rx.oldarg[1] = rx_old.arg[1];
|
||||
rx.oldarg[2] = rx_old.arg[2];
|
||||
rx.length = PM3_CMD_DATA_SIZE;
|
||||
memcpy(&rx.data, &rx_old.d, rx.length);
|
||||
PacketResponseReceived(&rx);
|
||||
if (rx.cmd == CMD_ACK) {
|
||||
ACK_received = true;
|
||||
PacketResponseReceived(&rx);
|
||||
}
|
||||
} else { // Old style reply
|
||||
PacketResponseOLD rx_old;
|
||||
memcpy(&rx_old, &rx_raw.pre, sizeof(PacketResponseNGPreamble));
|
||||
|
||||
res = uart_receive(sp, ((uint8_t *)&rx_old) + sizeof(PacketResponseNGPreamble), sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble), &rxlen);
|
||||
if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble))) {
|
||||
PrintAndLogEx(WARNING, "Received packet OLD frame with payload too short? %d/%zu", rxlen, sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble));
|
||||
error = true;
|
||||
}
|
||||
if (!error) {
|
||||
#ifdef COMMS_DEBUG
|
||||
PrintAndLogEx(NORMAL, "Receiving OLD:");
|
||||
#endif
|
||||
#ifdef COMMS_DEBUG_RAW
|
||||
print_hex_break((uint8_t *)&rx_old.cmd, sizeof(rx_old.cmd), 32);
|
||||
print_hex_break((uint8_t *)&rx_old.arg, sizeof(rx_old.arg), 32);
|
||||
print_hex_break((uint8_t *)&rx_old.d, sizeof(rx_old.d), 32);
|
||||
#endif
|
||||
rx.ng = false;
|
||||
rx.magic = 0;
|
||||
rx.status = 0;
|
||||
rx.crc = 0;
|
||||
rx.cmd = rx_old.cmd;
|
||||
rx.oldarg[0] = rx_old.arg[0];
|
||||
rx.oldarg[1] = rx_old.arg[1];
|
||||
rx.oldarg[2] = rx_old.arg[2];
|
||||
rx.length = PM3_CMD_DATA_SIZE;
|
||||
memcpy(&rx.data, &rx_old.d, rx.length);
|
||||
PacketResponseReceived(&rx);
|
||||
if (rx.cmd == CMD_ACK) {
|
||||
ACK_received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (rxlen > 0) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame preamble too short: %d/%zu", rxlen, sizeof(PacketResponseNGPreamble));
|
||||
error = true;
|
||||
}
|
||||
if (res == PM3_ENOTTY) {
|
||||
commfailed = true;
|
||||
} else {
|
||||
if (rxlen > 0) {
|
||||
PrintAndLogEx(WARNING, "Received packet frame preamble too short: %d/%zu", rxlen, sizeof(PacketResponseNGPreamble));
|
||||
error = true;
|
||||
}
|
||||
if (res == PM3_ENOTTY) {
|
||||
commfailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_receiving_raw_last = is_receiving_raw;
|
||||
// TODO if error, shall we resync ?
|
||||
|
||||
pthread_mutex_lock(&txBufferMutex);
|
||||
|
@ -560,6 +605,45 @@ bool IsCommunicationThreadDead(void) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// To start raw receive mode:
|
||||
// 1. Call SetCommunicationRawReceiveBuffer(...)
|
||||
// 2. Call SetCommunicationReceiveMode(true)
|
||||
//
|
||||
// To stop raw receive mode:
|
||||
// Call SetCommunicationReceiveMode(false)
|
||||
//
|
||||
// Note:
|
||||
// 1. The receiving thread won't accept any normal packets after calling
|
||||
// SetCommunicationReceiveMode(true). You need to call
|
||||
// SetCommunicationReceiveMode(false) to stop the raw receiving process.
|
||||
// 2. If the received size >= len used in SetCommunicationRawReceiveBuffer(),
|
||||
// The receiving thread will ignore the incoming data to prevent overflow.
|
||||
// 3. Normally you only need WaitForRawDataTimeout() rather than the
|
||||
// low level functions like SetCommunicationReceiveMode(),
|
||||
// SetCommunicationRawReceiveBuffer() and GetCommunicationRawReceiveNum()
|
||||
|
||||
bool SetCommunicationReceiveMode(bool isRawMode) {
|
||||
if (isRawMode) {
|
||||
uint8_t *buffer = __atomic_load_n(&comm_raw_data, __ATOMIC_SEQ_CST);
|
||||
if (buffer == NULL) {
|
||||
PrintAndLogEx(ERR, "Buffer for raw data is not set");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
__atomic_store_n(&comm_raw_mode, isRawMode, __ATOMIC_SEQ_CST);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetCommunicationRawReceiveBuffer(uint8_t *buffer, size_t len) {
|
||||
__atomic_store_n(&comm_raw_data, buffer, __ATOMIC_SEQ_CST);
|
||||
__atomic_store_n(&comm_raw_len, len, __ATOMIC_SEQ_CST);
|
||||
__atomic_store_n(&comm_raw_pos, 0, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
size_t GetCommunicationRawReceiveNum(void) {
|
||||
return __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) {
|
||||
|
||||
if (!wait_for_port) {
|
||||
|
@ -738,6 +822,78 @@ static size_t communication_delay(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wait for receiving a specified amount of bytes
|
||||
*
|
||||
* @param buffer The receive buffer
|
||||
* @param len The maximum receive byte size
|
||||
* @param ms_timeout the maximum timeout
|
||||
* @param show_process print how many bytes are received
|
||||
* @return the number of received bytes
|
||||
*/
|
||||
size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process) {
|
||||
uint8_t print_counter = 0;
|
||||
size_t last_pos = 0;
|
||||
|
||||
// Add delay depending on the communication channel & speed
|
||||
if (ms_timeout != (size_t) - 1) {
|
||||
ms_timeout += communication_delay();
|
||||
}
|
||||
__atomic_store_n(&timeout_start_time, msclock(), __ATOMIC_SEQ_CST);
|
||||
|
||||
SetCommunicationRawReceiveBuffer(buffer, len);
|
||||
SetCommunicationReceiveMode(true);
|
||||
|
||||
size_t pos = 0;
|
||||
while (pos < len) {
|
||||
|
||||
if (kbd_enter_pressed()) {
|
||||
// Send anything to stop the transfer
|
||||
PrintAndLogEx(INFO, "Stopping");
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
|
||||
// For ms_timeout == -1, pos < len might always be true
|
||||
// so user need a spectial way to break this loop
|
||||
if (ms_timeout == (size_t) - 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST);
|
||||
|
||||
// Check the timeout if pos is not updated
|
||||
if (last_pos == pos) {
|
||||
uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST);
|
||||
// If ms_timeout == -1, the loop can only be breaked by pressing Enter or receiving enough data
|
||||
if ((ms_timeout != (size_t) - 1) && (msclock() - tmp_clk > ms_timeout)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Print process when (print_counter % 64) == 0
|
||||
if (show_process && (print_counter & 0x3F) == 0) {
|
||||
PrintAndLogEx(INFO, "[%zu/%zu]", pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
print_counter++;
|
||||
last_pos = pos;
|
||||
msleep(10);
|
||||
}
|
||||
if (pos == len && (ms_timeout != (size_t) - 1)) {
|
||||
// If ms_timeout != -1, when the desired data is received, tell the arm side
|
||||
// to stop the current process, and wait for some time to make sure the process
|
||||
// has been stopped.
|
||||
// If ms_timeout == -1, the user might not want to break the existing process
|
||||
// on the arm side.
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
msleep(ms_timeout);
|
||||
}
|
||||
SetCommunicationReceiveMode(false);
|
||||
pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST);
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for a certain response type. This method waits for a maximum of
|
||||
* ms_timeout milliseconds for a specified response command.
|
||||
|
|
|
@ -45,6 +45,8 @@ extern "C" {
|
|||
#define CMD_BUFFER_SIZE 100
|
||||
#endif
|
||||
|
||||
#define COMM_RAW_RECEIVE_LEN (1024)
|
||||
|
||||
typedef enum {
|
||||
BIG_BUF,
|
||||
BIG_BUF_EML,
|
||||
|
@ -96,10 +98,14 @@ void clearCommandBuffer(void);
|
|||
|
||||
#define FLASHMODE_SPEED 460800
|
||||
bool IsCommunicationThreadDead(void);
|
||||
bool SetCommunicationReceiveMode(bool isRawMode);
|
||||
void SetCommunicationRawReceiveBuffer(uint8_t *buffer, size_t len);
|
||||
size_t GetCommunicationRawReceiveNum(void);
|
||||
bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed);
|
||||
int TestProxmark(pm3_device_t *dev);
|
||||
void CloseProxmark(pm3_device_t *dev);
|
||||
|
||||
size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process);
|
||||
bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout, bool show_warning);
|
||||
bool WaitForResponseTimeout(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout);
|
||||
bool WaitForResponse(uint32_t cmd, PacketResponseNG *response);
|
||||
|
@ -111,5 +117,3 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -113,12 +113,19 @@ void setGraphBuf(const uint8_t *src, size_t size) {
|
|||
RepaintGraphWindow();
|
||||
}
|
||||
|
||||
// This function assumes that the length of dest array >= g_GraphTraceLen.
|
||||
// If the length of dest array is less than g_GraphTraceLen, use getFromGraphBufEx(dest, maxLen) instead.
|
||||
size_t getFromGraphBuf(uint8_t *dest) {
|
||||
return getFromGraphBufEx(dest, g_GraphTraceLen);
|
||||
}
|
||||
|
||||
size_t getFromGraphBufEx(uint8_t *dest, size_t maxLen) {
|
||||
if (dest == NULL) return 0;
|
||||
if (g_GraphTraceLen == 0) return 0;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < g_GraphTraceLen; ++i) {
|
||||
maxLen = (maxLen < g_GraphTraceLen) ? maxLen : g_GraphTraceLen;
|
||||
for (i = 0; i < maxLen; ++i) {
|
||||
//trim
|
||||
if (g_GraphBuffer[i] > 127) g_GraphBuffer[i] = 127;
|
||||
if (g_GraphBuffer[i] < -127) g_GraphBuffer[i] = -127;
|
||||
|
@ -387,4 +394,3 @@ bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ bool HasGraphData(void);
|
|||
void setGraphBuf(const uint8_t *src, size_t size);
|
||||
void save_restoreGB(uint8_t saveOpt);
|
||||
size_t getFromGraphBuf(uint8_t *dest);
|
||||
size_t getFromGraphBufEx(uint8_t *dest, size_t maxLen);
|
||||
void convertGraphFromBitstream(void);
|
||||
void convertGraphFromBitstreamEx(int hi, int low);
|
||||
bool isGraphBitstream(void);
|
||||
|
@ -42,7 +43,7 @@ int GetNrzClock(const char *str, bool verbose);
|
|||
int GetFskClock(const char *str, bool verbose);
|
||||
bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge);
|
||||
|
||||
#define MAX_GRAPH_TRACE_LEN (40000 * 8)
|
||||
#define MAX_GRAPH_TRACE_LEN (40000 * 32)
|
||||
#define GRAPH_SAVE 1
|
||||
#define GRAPH_RESTORE 0
|
||||
|
||||
|
|
|
@ -37,10 +37,7 @@ AT91SAM7S256 USB Device Port
|
|||
#define AT91C_EP_IN 2 // cfg bulk in
|
||||
#define AT91C_EP_NOTIFY 3 // cfg cdc notification interrup
|
||||
|
||||
#define AT91C_EP_CONTROL_SIZE 8
|
||||
#define AT91C_EP_OUT_SIZE 64
|
||||
#define AT91C_EP_IN_SIZE 64
|
||||
|
||||
// The endpoint size is defined in usb_cdc.h
|
||||
|
||||
// Section: USB Descriptors
|
||||
#define USB_DESCRIPTOR_DEVICE 0x01 // DescriptorType for a Device Descriptor.
|
||||
|
@ -114,6 +111,7 @@ AT91SAM7S256 USB Device Port
|
|||
#define SET_LINE_CODING 0x2021
|
||||
#define SET_CONTROL_LINE_STATE 0x2221
|
||||
|
||||
static bool isAsyncRequestFinished = false;
|
||||
static AT91PS_UDP pUdp = AT91C_BASE_UDP;
|
||||
static uint8_t btConfiguration = 0;
|
||||
static uint8_t btConnection = 0;
|
||||
|
@ -127,7 +125,7 @@ static const char devDescriptor[] = {
|
|||
2, // Device Class: Communication Device Class
|
||||
0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ]
|
||||
0, // Device Protocol: CDC Device protocol (unused)
|
||||
AT91C_EP_CONTROL_SIZE, // MaxPacketSize0
|
||||
AT91C_USB_EP_CONTROL_SIZE, // MaxPacketSize0
|
||||
0xc4, 0x9a, // Vendor ID [0x9ac4 = J. Westhues]
|
||||
0x8f, 0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument]
|
||||
0x00, 0x01, // BCD Device release number (1.00)
|
||||
|
@ -217,7 +215,7 @@ static const char cfgDescriptor[] = {
|
|||
USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
|
||||
_EP03_IN, // EndpointAddress: Endpoint 03 - IN
|
||||
_INTERRUPT, // Attributes
|
||||
AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8
|
||||
AT91C_USB_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8
|
||||
0xFF, // Interval polling
|
||||
|
||||
|
||||
|
@ -238,7 +236,7 @@ static const char cfgDescriptor[] = {
|
|||
USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
|
||||
_EP01_OUT, // Endpoint Address: Endpoint 01 - OUT
|
||||
_BULK, // Attributes: BULK
|
||||
AT91C_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes
|
||||
AT91C_USB_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes
|
||||
0, // Interval: ignored for bulk
|
||||
|
||||
/* Endpoint descriptor */
|
||||
|
@ -246,7 +244,7 @@ static const char cfgDescriptor[] = {
|
|||
USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
|
||||
_EP02_IN, // Endpoint Address: Endpoint 02 - IN
|
||||
_BULK, // Attribute: BULK
|
||||
AT91C_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes
|
||||
AT91C_USB_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes
|
||||
0 // Interval: ignored for bulk
|
||||
};
|
||||
|
||||
|
@ -638,6 +636,10 @@ bool usb_poll(void) {
|
|||
return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
|
||||
}
|
||||
|
||||
inline uint16_t usb_available_length(void) {
|
||||
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
In github PR #129, some users appears to get a false positive from
|
||||
usb_poll, which returns true, but the usb_read operation
|
||||
|
@ -649,7 +651,7 @@ bool usb_poll(void) {
|
|||
bool usb_poll_validate_length(void) {
|
||||
if (!usb_check()) return false;
|
||||
if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
|
||||
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0;
|
||||
return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -671,7 +673,7 @@ uint32_t usb_read(uint8_t *data, size_t len) {
|
|||
|
||||
if (pUdp->UDP_CSR[AT91C_EP_OUT] & bank) {
|
||||
|
||||
packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16;
|
||||
packetSize = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
|
||||
packetSize = MIN(packetSize, len);
|
||||
len -= packetSize;
|
||||
while (packetSize--)
|
||||
|
@ -727,7 +729,7 @@ uint32_t usb_read_ng(uint8_t *data, size_t len) {
|
|||
|
||||
if ((pUdp->UDP_CSR[AT91C_EP_OUT] & bank)) {
|
||||
|
||||
uint32_t available = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16;
|
||||
uint32_t available = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16);
|
||||
packetSize = MIN(available, len);
|
||||
available -= packetSize;
|
||||
len -= packetSize;
|
||||
|
@ -770,7 +772,7 @@ int usb_write(const uint8_t *data, const size_t len) {
|
|||
|
||||
|
||||
// send first chunk
|
||||
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
||||
cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
|
||||
length -= cpt;
|
||||
while (cpt--) {
|
||||
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
|
||||
|
@ -781,7 +783,7 @@ int usb_write(const uint8_t *data, const size_t len) {
|
|||
|
||||
while (length) {
|
||||
// Send next chunk
|
||||
cpt = MIN(length, AT91C_EP_IN_SIZE);
|
||||
cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
|
||||
length -= cpt;
|
||||
while (cpt--) {
|
||||
pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
|
||||
|
@ -809,7 +811,7 @@ int usb_write(const uint8_t *data, const size_t len) {
|
|||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
|
||||
|
||||
|
||||
if (len % AT91C_EP_IN_SIZE == 0) {
|
||||
if (len % AT91C_USB_EP_IN_SIZE == 0) {
|
||||
// like AT91F_USB_SendZlp(), in non ping-pong mode
|
||||
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
||||
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {};
|
||||
|
@ -821,6 +823,117 @@ int usb_write(const uint8_t *data, const size_t len) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* \fn async_usb_write_start
|
||||
* \brief Start async write process
|
||||
* \return PM3_EIO if USB is invalid, PM3_SUCCESS if it is ready for write
|
||||
*
|
||||
* This function checks if the USB is connected, and wait until the FIFO
|
||||
* is ready to be filled.
|
||||
*
|
||||
* Warning: usb_write() should not be called between
|
||||
* async_usb_write_start() and async_usb_write_stop().
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
int async_usb_write_start(void) {
|
||||
|
||||
if (!usb_check()) return PM3_EIO;
|
||||
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
|
||||
if (!usb_check()) return PM3_EIO;
|
||||
}
|
||||
|
||||
isAsyncRequestFinished = false;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* \fn async_usb_write_pushByte
|
||||
* \brief Push one byte to the FIFO of IN endpoint (time-critical)
|
||||
*
|
||||
* This function simply push a byte to the FIFO of IN endpoint.
|
||||
* The FIFO size is AT91C_USB_EP_IN_SIZE. Make sure this function is not called
|
||||
* over AT91C_USB_EP_IN_SIZE times between each async_usb_write_requestWrite().
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
inline void async_usb_write_pushByte(uint8_t data) {
|
||||
pUdp->UDP_FDR[AT91C_EP_IN] = data;
|
||||
isAsyncRequestFinished = false;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* \fn async_usb_write_requestWrite
|
||||
* \brief Request a write operation (time-critical)
|
||||
* \return false if the last write request is not finished, true if success
|
||||
*
|
||||
* This function requests a write operation from FIFO to the USB bus,
|
||||
* and switch the internal banks of FIFO. It doesn't wait for the end of
|
||||
* transmission from FIFO to the USB bus.
|
||||
*
|
||||
* Note: This function doesn't check if the usb is valid, as it is
|
||||
* time-critical.
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
inline bool async_usb_write_requestWrite(void) {
|
||||
|
||||
// check if last request is finished
|
||||
if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// clear transmission completed flag
|
||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
|
||||
|
||||
// start of transmission
|
||||
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
||||
|
||||
// hack: no need to wait if UDP_CSR and UDP_FDR are not used immediately.
|
||||
// while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
|
||||
isAsyncRequestFinished = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* \fn async_usb_write_stop
|
||||
* \brief Stop async write process
|
||||
* \return PM3_EIO if USB is invalid, PM3_SUCCESS if data is written
|
||||
*
|
||||
* This function makes sure the data left in the FIFO is written to the
|
||||
* USB bus.
|
||||
*
|
||||
* Warning: usb_write() should not be called between
|
||||
* async_usb_write_start() and async_usb_write_stop().
|
||||
*----------------------------------------------------------------------------
|
||||
*/
|
||||
int async_usb_write_stop(void) {
|
||||
// Wait for the end of transfer
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
|
||||
if (!usb_check()) return PM3_EIO;
|
||||
}
|
||||
|
||||
// clear transmission completed flag
|
||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
|
||||
|
||||
// FIFO is not empty, request a write in non-ping-pong mode
|
||||
if (isAsyncRequestFinished == false) {
|
||||
UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
|
||||
|
||||
while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
|
||||
if (!usb_check()) return PM3_EIO;
|
||||
}
|
||||
|
||||
UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
|
||||
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* \fn AT91F_USB_SendData
|
||||
|
@ -831,7 +944,7 @@ void AT91F_USB_SendData(AT91PS_UDP pudp, const char *pData, uint32_t length) {
|
|||
AT91_REG csr;
|
||||
|
||||
do {
|
||||
uint32_t cpt = MIN(length, AT91C_EP_CONTROL_SIZE);
|
||||
uint32_t cpt = MIN(length, AT91C_USB_EP_CONTROL_SIZE);
|
||||
length -= cpt;
|
||||
|
||||
while (cpt--)
|
||||
|
|
|
@ -23,13 +23,22 @@
|
|||
#include "common.h"
|
||||
#include "at91sam7s512.h"
|
||||
|
||||
#define AT91C_USB_EP_CONTROL_SIZE 8
|
||||
#define AT91C_USB_EP_OUT_SIZE 64
|
||||
#define AT91C_USB_EP_IN_SIZE 64
|
||||
|
||||
void usb_disable(void);
|
||||
void usb_enable(void);
|
||||
bool usb_check(void);
|
||||
bool usb_poll(void);
|
||||
uint16_t usb_available_length(void);
|
||||
bool usb_poll_validate_length(void);
|
||||
uint32_t usb_read(uint8_t *data, size_t len);
|
||||
int usb_write(const uint8_t *data, const size_t len);
|
||||
int async_usb_write_start(void);
|
||||
void async_usb_write_pushByte(uint8_t data);
|
||||
bool async_usb_write_requestWrite(void);
|
||||
int async_usb_write_stop(void);
|
||||
uint32_t usb_read_ng(uint8_t *data, size_t len);
|
||||
void usb_update_serial(uint64_t newSerialNumber);
|
||||
|
||||
|
|
|
@ -196,4 +196,21 @@ extern bool g_tearoff_enabled;
|
|||
#define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8)))
|
||||
#define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8)))
|
||||
|
||||
// time for decompressing and loading the image to the FPGA
|
||||
#define FPGA_LOAD_WAIT_TIME (1500)
|
||||
|
||||
// GCC extension
|
||||
// from client/deps/tinycbor/compilersupport_p.h
|
||||
#ifdef __GNUC__
|
||||
#ifndef likely
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
#else
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -274,6 +274,17 @@ typedef struct {
|
|||
uint8_t data[];
|
||||
} PACKED lf_hitag_t;
|
||||
|
||||
// For CMD_LF_SNIFF_RAW_ADC and CMD_LF_ACQ_RAW_ADC
|
||||
#define LF_SAMPLES_BITS 30
|
||||
#define MAX_LF_SAMPLES ((((uint32_t)1u) << LF_SAMPLES_BITS) - 1)
|
||||
|
||||
typedef struct {
|
||||
// 64KB SRAM -> 524288 bits(max sample num) < 2^30
|
||||
uint32_t samples : LF_SAMPLES_BITS;
|
||||
bool realtime : 1;
|
||||
bool verbose : 1;
|
||||
} PACKED lf_sample_payload_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t blockno;
|
||||
uint8_t keytype;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue