Receive raw data on the client

This commit is contained in:
wh201906 2023-11-14 02:17:45 +08:00
commit 8fdf04fcfb
No known key found for this signature in database
2 changed files with 260 additions and 107 deletions

View file

@ -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.

View file

@ -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