From 96aab0688a3be310deb2b6618273203d13e5f119 Mon Sep 17 00:00:00 2001 From: LW Date: Mon, 11 Dec 2017 01:56:20 -0800 Subject: [PATCH] First try at disconnect/reconnect detection. No idea if it's going to work on WIN32. --- client/cmdhw.c | 10 +++++++- client/cmdhw.h | 1 + client/proxmark3.c | 61 +++++++++++++++++++++++++++++++++++++++++----- uart/uart_posix.c | 12 ++++----- 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 8f7243ad..2451ca77 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -405,11 +405,19 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { + return CmdVersionC(Cmd, false); +} - clearCommandBuffer(); +int CmdVersionC(const char *Cmd, const bool no_cache) +{ UsbCommand c = {CMD_VERSION}; static UsbCommand resp = {0, {0, 0, 0}}; + if( no_cache ) + memset( &resp, 0, sizeof(resp) ); + else + clearCommandBuffer(); + if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { diff --git a/client/cmdhw.h b/client/cmdhw.h index b8e10f74..c4d6a836 100644 --- a/client/cmdhw.h +++ b/client/cmdhw.h @@ -23,5 +23,6 @@ int CmdSetDivisor(const char *Cmd); int CmdSetMux(const char *Cmd); int CmdTune(const char *Cmd); int CmdVersion(const char *Cmd); +int CmdVersionC(const char *Cmd, const bool no_cache); #endif diff --git a/client/proxmark3.c b/client/proxmark3.c index 99ba9fba..07485e0b 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -38,6 +38,7 @@ pthread_mutex_t print_lock; static serial_port sp; +static char* sp_name; static UsbCommand txcmd; volatile static bool txcmd_pending = false; @@ -70,16 +71,63 @@ byte_t* prx = rx; static void *uart_receiver(void *targ) { struct receiver_arg *arg = (struct receiver_arg*)targ; size_t rxlen; + bool need_reconnect = false; + UsbCommand version_cmd = {CMD_VERSION}; + static bool request_version = false; while (arg->run) { - rxlen = 0; - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { - prx += rxlen; - if (prx-rx < sizeof(UsbCommand)) { + if( need_reconnect ) { + sp = uart_open(sp_name); + + if( sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT ) + { + PrintAndLog("Reconnect failed, retrying..."); + + if( txcmd_pending ) { + PrintAndLog("Cannot send bytes to offline proxmark"); + txcmd_pending = false; + } + + sleep(2); continue; } - UsbCommandReceived((UsbCommand*)rx); + + PrintAndLog("Proxmark reconnected!"); + need_reconnect = false; + offline = 0; + //CmdVersionW(NULL, true); + clearCommandBuffer(); + uart_send(sp, (byte_t*) &version_cmd, sizeof(UsbCommand)); // request it from the HW + request_version = true; } + + rxlen = 0; + if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) ) { + if( rxlen ) { + prx += rxlen; + if (prx-rx < sizeof(UsbCommand)) { + continue; + } + + UsbCommandReceived((UsbCommand*)rx); + + if( request_version && ((UsbCommand*)rx)->cmd == CMD_ACK) + { + request_version = false; + CmdVersionW(NULL, true); + } + } + } + else { + PrintAndLog("Receiving data from proxmark failed, attempting a reconnect"); + uart_close(sp); + sp = INVALID_SERIAL_PORT; + offline = 1; + txcmd_pending = false; + need_reconnect = true; + continue; + } + prx = rx; if(txcmd_pending) { @@ -351,6 +399,7 @@ int main(int argc, char* argv[]) { set_my_executable_path(); // open uart + sp_name = argv[1]; if (!waitCOMPort) { sp = uart_open(argv[1]); } else { @@ -405,7 +454,7 @@ int main(int argc, char* argv[]) { #endif // Clean up the port - if (usb_present) { + if (sp != INVALID_SERIAL_PORT && sp != CLAIMED_SERIAL_PORT) { uart_close(sp); } diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 45e0d3d2..59b12956 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -141,7 +141,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ // Reset the output count *pszRxLen = 0; - + do { // Reset file descriptor FD_ZERO(&rfds); @@ -153,12 +153,12 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ if (res < 0) { return false; } - + // Read time-out if (res == 0) { if (*pszRxLen == 0) { // Error, we received no data - return false; + return true; } else { // We received some data, but nothing more is available return true; @@ -168,7 +168,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ // Retrieve the count of the incoming bytes res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); if (res < 0) return false; - + // Cap the number of bytes, so we don't overrun the buffer if (pszMaxRxLen - (*pszRxLen) < byteCount) { byteCount = pszMaxRxLen - (*pszRxLen); @@ -178,8 +178,8 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ res = read(((serial_port_unix*)sp)->fd, pbtRx+(*pszRxLen), byteCount); // Stop if the OS has some troubles reading the data - if (res <= 0) return false; - + if (res < 0) return false; + *pszRxLen += res; if (*pszRxLen == pszMaxRxLen) {