diff --git a/client/comms.c b/client/comms.c index 2c809cae7..1f3fbb30a 100644 --- a/client/comms.c +++ b/client/comms.c @@ -22,11 +22,13 @@ // Serial port that we are communicating with the PM3 on. static serial_port sp = NULL; static char *serial_port_name = NULL; +static uint32_t _speed = 0; communication_arg_t conn; capabilities_t pm3_capabilities; -static pthread_t USB_communication_thread; +static pthread_t communication_thread; +static bool comm_thread_dead = false; // Transmit buffer. 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 #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) @@ -340,20 +319,27 @@ __attribute__((force_align_arg_pointer)) *uart_communication(void *targ) { communication_arg_t *connection = (communication_arg_t *)targ; uint32_t rxlen; - + uint8_t counter_to_offline = 0; PacketResponseNG rx; PacketResponseNGRaw rx_raw; - //int counter_to_offline = 0; #if defined(__MACH__) && defined(__APPLE__) disableAppNap("Proxmark3 polling UART"); #endif +// is this connection->run a cross thread call? + while (connection->run) { rxlen = 0; bool ACK_received = 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); 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); if (txBufferNGLen) { // NG packet if (!uart_send(sp, (uint8_t *) &txBufferNG, txBufferNGLen)) { - //counter_to_offline++; + counter_to_offline++; PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed")); } conn.last_command = txBufferNG.pre.cmd; txBufferNGLen = 0; } else { if (!uart_send(sp, (uint8_t *) &txBuffer, sizeof(PacketCommandOLD))) { - //counter_to_offline++; + counter_to_offline++; PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device " _RED_("failed")); } conn.last_command = txBuffer.cmd; @@ -514,18 +500,30 @@ __attribute__((force_align_arg_pointer)) 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); sp = NULL; #if defined(__MACH__) && defined(__APPLE__) enableAppNap(); #endif - + pthread_exit(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) { 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) { PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "invalid serial port " _YELLOW_("%s"), portname); sp = NULL; - serial_port_name = NULL; + //serial_port_name = NULL; return false; } else if (sp == CLAIMED_SERIAL_PORT) { PrintAndLogEx(WARNING, "\n" _RED_("ERROR:") "serial port " _YELLOW_("%s") " is claimed by another process", portname); sp = NULL; - serial_port_name = NULL; + //serial_port_name = NULL; return false; } else { - // start the USB communication thread + // start the communication thread serial_port_name = portname; + _speed = speed; conn.run = true; conn.block_after_ACK = flash_mode; // 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 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); // create a mutex to avoid interlacing print commands from our different threads @@ -583,16 +582,20 @@ int TestProxmark(void) { uint8_t data[len]; for (uint16_t i = 0; i < len; i++) data[i] = i & 0xFF; + SendCommandNG(CMD_PING, data, len); + + uint32_t timeout = 1000; + #ifdef USART_SLOW_LINK + timeout = 10000; // 10s timeout for slow FPC, e.g. over BT // as this is the very first command sent to the pm3 - // that initiates the BT connection - if (WaitForResponseTimeoutW(CMD_PING, &resp, 10000, false)) { -#else - if (WaitForResponseTimeoutW(CMD_PING, &resp, 1000, false)) { + // that initiates the BT connection #endif + if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false)) { + bool error = false; if (len) error = memcmp(data, resp.data.asBytes, len) != 0; @@ -600,6 +603,7 @@ int TestProxmark(void) { return PM3_EIO; SendCommandNG(CMD_CAPABILITIES, NULL, 0); + if (WaitForResponseTimeoutW(CMD_PING, &resp, 1000, false)) { memcpy(&pm3_capabilities, resp.data.asBytes, resp.length); conn.send_via_fpc_usart = pm3_capabilities.via_fpc; @@ -619,10 +623,8 @@ int TestProxmark(void) { pthread_mutex_unlock(&spMutex); #endif if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "UART reconfigure failed"); return res; } - } return PM3_SUCCESS; } else { @@ -637,11 +639,11 @@ void CloseProxmark(void) { conn.run = false; #ifdef __BIONIC__ - if (USB_communication_thread != 0) { - pthread_join(USB_communication_thread, NULL); + if (communication_thread != 0) { + pthread_join(communication_thread, NULL); } #else - pthread_join(USB_communication_thread, NULL); + pthread_join(communication_thread, NULL); #endif if (sp) { @@ -660,7 +662,7 @@ void CloseProxmark(void) { // Clean up our state sp = 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 diff --git a/client/comms.h b/client/comms.h index ff1edbbcc..70c0526bf 100644 --- a/client/comms.h +++ b/client/comms.h @@ -62,6 +62,8 @@ void SendCommandMIX(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, v void clearCommandBuffer(void); #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); int TestProxmark(void); void CloseProxmark(void); diff --git a/client/proxmark3.c b/client/proxmark3.c index 170d97b58..c5bfb1cb2 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -52,6 +52,7 @@ static void showBanner(void) { fflush(stdout); } +// Main thread of PM3 Client void #ifdef __has_attribute #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... while (1) { bool printprompt = false; - // this should hook up the PM3 again. - /* - if ( !session.pm3_present ) { - - // sets the global variable, SP and offline) - session.pm3_present = hookUpPM3(); - - // usb and the reader_thread is NULL, create a new reader thread. - 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 communications thread goes down. Device disconnected then this should hook up PM3 again. + if ( IsCommunicationThreadDead() ) { + PrintAndLogEx(ERR, _RED_("ERROR:") "cannot communicate with the Proxmark, waiting for device to reconnect..."); + session.pm3_present = ReConnectProxmark(); + if (session.pm3_present && (TestProxmark() != PM3_SUCCESS)) { + session.pm3_present = false; + continue; } } - */ // If there is a script file if (sf) { @@ -190,12 +182,13 @@ main_loop(char *script_cmds_file, char *script_cmd) { if (cmd[0] != '\0') { if (printprompt) PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd); + int ret = CommandReceived(cmd); + HIST_ENTRY *entry = history_get(history_length); if ((!entry) || (strcmp(entry->line, cmd) != 0)) add_history(cmd); -// PrintAndLogEx(NORMAL, "RETVAL: %d\n", ret); // exit or quit if (ret == PM3_EFATAL) break; @@ -409,7 +402,7 @@ int main(int argc, char *argv[]) { continue; } - // execute pm3 command + // execute pm3 command file if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--script-file") == 0) { if (i + 1 == argc) { PrintAndLogEx(ERR, _RED_("ERROR:") "missing script file specification after -s\n");