chg: reconnect to a disconnected proxmark3 device without restarting the client. Old functionality restored :)

chg: renamed thread
chg: easier if-statements for USART
This commit is contained in:
iceman1001 2019-05-06 14:11:23 +02:00
commit cffd14a96b
3 changed files with 63 additions and 66 deletions

View file

@ -22,11 +22,13 @@
// Serial port that we are communicating with the PM3 on. // Serial port that we are communicating with the PM3 on.
static serial_port sp = NULL; static serial_port sp = NULL;
static char *serial_port_name = NULL; static char *serial_port_name = NULL;
static uint32_t _speed = 0;
communication_arg_t conn; communication_arg_t conn;
capabilities_t pm3_capabilities; capabilities_t pm3_capabilities;
static pthread_t USB_communication_thread; static pthread_t communication_thread;
static bool comm_thread_dead = false;
// Transmit buffer. // Transmit buffer.
static PacketCommandOLD txBuffer; static PacketCommandOLD txBuffer;
@ -304,33 +306,10 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
} }
} }
/*
bool hookUpPM3() {
bool ret = false;
sp = uart_open( comport, speed );
if (sp == INVALID_SERIAL_PORT) {
PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: invalid serial port)\n");
sp = NULL;
serial_port_name = NULL;
ret = false;
session.pm3_present = false;
} else if (sp == CLAIMED_SERIAL_PORT) {
PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: serial port is claimed by another process)\n");
sp = NULL;
serial_port_name = NULL;
ret = false;
session.pm3_present = false;
} else {
PrintAndLogEx(SUCCESS, "Proxmark3 reconnected\n");
serial_port_name = ;
ret = true;
session.pm3_present = true;
}
return ret;
}
*/
// The communications thread.
// signals to main thread when a response is ready to process.
//
static void static void
#ifdef __has_attribute #ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer) #if __has_attribute(force_align_arg_pointer)
@ -340,20 +319,27 @@ __attribute__((force_align_arg_pointer))
*uart_communication(void *targ) { *uart_communication(void *targ) {
communication_arg_t *connection = (communication_arg_t *)targ; communication_arg_t *connection = (communication_arg_t *)targ;
uint32_t rxlen; uint32_t rxlen;
uint8_t counter_to_offline = 0;
PacketResponseNG rx; PacketResponseNG rx;
PacketResponseNGRaw rx_raw; PacketResponseNGRaw rx_raw;
//int counter_to_offline = 0;
#if defined(__MACH__) && defined(__APPLE__) #if defined(__MACH__) && defined(__APPLE__)
disableAppNap("Proxmark3 polling UART"); disableAppNap("Proxmark3 polling UART");
#endif #endif
// is this connection->run a cross thread call?
while (connection->run) { while (connection->run) {
rxlen = 0; rxlen = 0;
bool ACK_received = false; bool ACK_received = false;
bool error = false; bool error = false;
// three failed attempts
if ( counter_to_offline >= 3 ) {
__atomic_test_and_set(&comm_thread_dead, __ATOMIC_SEQ_CST);
break;
}
pthread_mutex_lock(&spMutex); pthread_mutex_lock(&spMutex);
if (uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen) && (rxlen == sizeof(PacketResponseNGPreamble))) { if (uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen) && (rxlen == sizeof(PacketResponseNGPreamble))) {
@ -491,14 +477,14 @@ __attribute__((force_align_arg_pointer))
pthread_mutex_lock(&spMutex); pthread_mutex_lock(&spMutex);
if (txBufferNGLen) { // NG packet if (txBufferNGLen) { // NG packet
if (!uart_send(sp, (uint8_t *) &txBufferNG, txBufferNGLen)) { if (!uart_send(sp, (uint8_t *) &txBufferNG, txBufferNGLen)) {
//counter_to_offline++; counter_to_offline++;
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed")); PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed"));
} }
conn.last_command = txBufferNG.pre.cmd; conn.last_command = txBufferNG.pre.cmd;
txBufferNGLen = 0; txBufferNGLen = 0;
} else { } else {
if (!uart_send(sp, (uint8_t *) &txBuffer, sizeof(PacketCommandOLD))) { if (!uart_send(sp, (uint8_t *) &txBuffer, sizeof(PacketCommandOLD))) {
//counter_to_offline++; counter_to_offline++;
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed")); PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed"));
} }
conn.last_command = txBuffer.cmd; conn.last_command = txBuffer.cmd;
@ -514,18 +500,30 @@ __attribute__((force_align_arg_pointer))
pthread_mutex_unlock(&txBufferMutex); pthread_mutex_unlock(&txBufferMutex);
} }
// when this reader thread dies, we close the serial port. // when thread dies, we close the serial port.
uart_close(sp); uart_close(sp);
sp = NULL; sp = NULL;
#if defined(__MACH__) && defined(__APPLE__) #if defined(__MACH__) && defined(__APPLE__)
enableAppNap(); enableAppNap();
#endif #endif
pthread_exit(NULL); pthread_exit(NULL);
return NULL; return NULL;
} }
bool IsCommunicationThreadDead(void) {
return comm_thread_dead;
}
bool ReConnectProxmark(void) {
char *port = serial_port_name;
bool res = OpenProxmark(port, true, 20, false, _speed);
if ( res )
__atomic_clear(&comm_thread_dead, __ATOMIC_SEQ_CST);
return res;
}
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) { bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) {
char *portname = (char *)port; char *portname = (char *)port;
@ -548,16 +546,17 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode,
if (sp == INVALID_SERIAL_PORT) { if (sp == INVALID_SERIAL_PORT) {
PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "invalid serial port " _YELLOW_("%s"), portname); PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "invalid serial port " _YELLOW_("%s"), portname);
sp = NULL; sp = NULL;
serial_port_name = NULL; //serial_port_name = NULL;
return false; return false;
} else if (sp == CLAIMED_SERIAL_PORT) { } else if (sp == CLAIMED_SERIAL_PORT) {
PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "serial port " _YELLOW_("%s") " is claimed by another process", portname); PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "serial port " _YELLOW_("%s") " is claimed by another process", portname);
sp = NULL; sp = NULL;
serial_port_name = NULL; //serial_port_name = NULL;
return false; return false;
} else { } else {
// start the USB communication thread // start the communication thread
serial_port_name = portname; serial_port_name = portname;
_speed = speed;
conn.run = true; conn.run = true;
conn.block_after_ACK = flash_mode; conn.block_after_ACK = flash_mode;
// Flags to tell where to add CRC on sent replies // Flags to tell where to add CRC on sent replies
@ -566,7 +565,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode,
// "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART // "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
conn.send_via_fpc_usart = false; conn.send_via_fpc_usart = false;
pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); pthread_create(&communication_thread, NULL, &uart_communication, &conn);
fflush(stdout); fflush(stdout);
// create a mutex to avoid interlacing print commands from our different threads // create a mutex to avoid interlacing print commands from our different threads
@ -583,16 +582,20 @@ int TestProxmark(void) {
uint8_t data[len]; uint8_t data[len];
for (uint16_t i = 0; i < len; i++) for (uint16_t i = 0; i < len; i++)
data[i] = i & 0xFF; data[i] = i & 0xFF;
SendCommandNG(CMD_PING, data, len); SendCommandNG(CMD_PING, data, len);
uint32_t timeout = 1000;
#ifdef USART_SLOW_LINK #ifdef USART_SLOW_LINK
timeout = 10000;
// 10s timeout for slow FPC, e.g. over BT // 10s timeout for slow FPC, e.g. over BT
// as this is the very first command sent to the pm3 // as this is the very first command sent to the pm3
// that initiates the BT connection // that initiates the BT connection
if (WaitForResponseTimeoutW(CMD_PING, &resp, 10000, false)) {
#else
if (WaitForResponseTimeoutW(CMD_PING, &resp, 1000, false)) {
#endif #endif
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false)) {
bool error = false; bool error = false;
if (len) if (len)
error = memcmp(data, resp.data.asBytes, len) != 0; error = memcmp(data, resp.data.asBytes, len) != 0;
@ -600,6 +603,7 @@ int TestProxmark(void) {
return PM3_EIO; return PM3_EIO;
SendCommandNG(CMD_CAPABILITIES, NULL, 0); SendCommandNG(CMD_CAPABILITIES, NULL, 0);
if (WaitForResponseTimeoutW(CMD_PING, &resp, 1000, false)) { if (WaitForResponseTimeoutW(CMD_PING, &resp, 1000, false)) {
memcpy(&pm3_capabilities, resp.data.asBytes, resp.length); memcpy(&pm3_capabilities, resp.data.asBytes, resp.length);
conn.send_via_fpc_usart = pm3_capabilities.via_fpc; conn.send_via_fpc_usart = pm3_capabilities.via_fpc;
@ -619,10 +623,8 @@ int TestProxmark(void) {
pthread_mutex_unlock(&spMutex); pthread_mutex_unlock(&spMutex);
#endif #endif
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(ERR, "UART reconfigure failed");
return res; return res;
} }
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} else { } else {
@ -637,11 +639,11 @@ void CloseProxmark(void) {
conn.run = false; conn.run = false;
#ifdef __BIONIC__ #ifdef __BIONIC__
if (USB_communication_thread != 0) { if (communication_thread != 0) {
pthread_join(USB_communication_thread, NULL); pthread_join(communication_thread, NULL);
} }
#else #else
pthread_join(USB_communication_thread, NULL); pthread_join(communication_thread, NULL);
#endif #endif
if (sp) { if (sp) {
@ -660,7 +662,7 @@ void CloseProxmark(void) {
// Clean up our state // Clean up our state
sp = NULL; sp = NULL;
serial_port_name = NULL; serial_port_name = NULL;
memset(&USB_communication_thread, 0, sizeof(pthread_t)); memset(&communication_thread, 0, sizeof(pthread_t));
} }
// Gives a rough estimate of the communication delay based on channel & baudrate // Gives a rough estimate of the communication delay based on channel & baudrate

View file

@ -62,6 +62,8 @@ void SendCommandMIX(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, v
void clearCommandBuffer(void); void clearCommandBuffer(void);
#define FLASHMODE_SPEED 460800 #define FLASHMODE_SPEED 460800
bool IsCommunicationThreadDead(void);
bool ReConnectProxmark(void);
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed); bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed);
int TestProxmark(void); int TestProxmark(void);
void CloseProxmark(void); void CloseProxmark(void);

View file

@ -52,6 +52,7 @@ static void showBanner(void) {
fflush(stdout); fflush(stdout);
} }
// Main thread of PM3 Client
void void
#ifdef __has_attribute #ifdef __has_attribute
#if __has_attribute(force_align_arg_pointer) #if __has_attribute(force_align_arg_pointer)
@ -95,25 +96,16 @@ main_loop(char *script_cmds_file, char *script_cmd) {
// loops every time enter is pressed... // loops every time enter is pressed...
while (1) { while (1) {
bool printprompt = false; bool printprompt = false;
// this should hook up the PM3 again.
/* // If communications thread goes down. Device disconnected then this should hook up PM3 again.
if ( !session.pm3_present ) { if ( IsCommunicationThreadDead() ) {
PrintAndLogEx(ERR, _RED_("ERROR:") "cannot communicate with the Proxmark, waiting for device to reconnect...");
// sets the global variable, SP and offline) session.pm3_present = ReConnectProxmark();
session.pm3_present = hookUpPM3(); if (session.pm3_present && (TestProxmark() != PM3_SUCCESS)) {
session.pm3_present = false;
// usb and the reader_thread is NULL, create a new reader thread. continue;
if (session.pm3_present) {
rarg.run = 1;
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
// cache Version information now:
if ( execCommand || script_cmds_file || stdinOnPipe)
CmdVersion("s");
else
CmdVersion("");
} }
} }
*/
// If there is a script file // If there is a script file
if (sf) { if (sf) {
@ -190,12 +182,13 @@ main_loop(char *script_cmds_file, char *script_cmd) {
if (cmd[0] != '\0') { if (cmd[0] != '\0') {
if (printprompt) if (printprompt)
PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd); PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd);
int ret = CommandReceived(cmd); int ret = CommandReceived(cmd);
HIST_ENTRY *entry = history_get(history_length); HIST_ENTRY *entry = history_get(history_length);
if ((!entry) || (strcmp(entry->line, cmd) != 0)) if ((!entry) || (strcmp(entry->line, cmd) != 0))
add_history(cmd); add_history(cmd);
// PrintAndLogEx(NORMAL, "RETVAL: %d\n", ret);
// exit or quit // exit or quit
if (ret == PM3_EFATAL) if (ret == PM3_EFATAL)
break; break;
@ -409,7 +402,7 @@ int main(int argc, char *argv[]) {
continue; continue;
} }
// execute pm3 command // execute pm3 command file
if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--script-file") == 0) { if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--script-file") == 0) {
if (i + 1 == argc) { if (i + 1 == argc) {
PrintAndLogEx(ERR, _RED_("ERROR:") "missing script file specification after -s\n"); PrintAndLogEx(ERR, _RED_("ERROR:") "missing script file specification after -s\n");