mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
Receive raw data on the client
This commit is contained in:
parent
b4cc7c02cd
commit
8fdf04fcfb
2 changed files with 260 additions and 107 deletions
|
@ -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,6 +374,47 @@ __attribute__((force_align_arg_pointer))
|
|||
break;
|
||||
}
|
||||
|
||||
bool is_receiving_raw = __atomic_load_n(&comm_raw_mode, __ATOMIC_SEQ_CST);
|
||||
|
||||
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);
|
||||
|
||||
// set the buffer as undefined
|
||||
// comm_raw_data == NULL is used in SetCommunicationReceiveMode()
|
||||
__atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
} else {
|
||||
if (is_receiving_raw_last) {
|
||||
// is_receiving_raw changed from true to false
|
||||
|
||||
// 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);
|
||||
|
||||
if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) {
|
||||
|
@ -497,7 +544,9 @@ __attribute__((force_align_arg_pointer))
|
|||
commfailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is_receiving_raw_last = is_receiving_raw;
|
||||
// TODO if error, shall we resync ?
|
||||
|
||||
pthread_mutex_lock(&txBufferMutex);
|
||||
|
@ -560,6 +609,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 +826,67 @@ 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);
|
||||
}
|
||||
|
||||
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 ((msclock() - tmp_clk > ms_timeout)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// print 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) {
|
||||
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||
msleep(ms_timeout);
|
||||
}
|
||||
SetCommunicationReceiveMode(false);
|
||||
pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST);
|
||||
PrintAndLogEx(INFO, "Done: [%zu/%zu]", pos, len);
|
||||
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
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue