CORESRCS =     uart_posix.c \
                        uart_win32.c \
                        util.c \
-                       util_posix.c
+                       util_posix.c \
+                       ui.c \
+                       comms.c
 
 CMDSRCS =      crapto1/crapto1.c\
                        crapto1/crypto1.c\
                        iso14443crc.c \
                        iso15693tools.c \
                        graph.c \
-                       ui.c \
                        cmddata.c \
                        lfdemod.c \
                        emv/crypto_polarssl.c\
                        cmdscript.c\
                        pm3_binlib.c\
                        pm3_bitlib.c\
-                       protocols.c\
-                       comms.c
+                       protocols.c
 
 cpu_arch = $(shell uname -m)
 ifneq ($(findstring 86, $(cpu_arch)), )
 
 // Data and Graph commands
 //-----------------------------------------------------------------------------
 
+#include "cmddata.h"
+
 #include <stdio.h>    // also included in util.h
 #include <string.h>   // also included in util.h
 #include <inttypes.h>
 #include <limits.h>   // for CmdNorm INT_MIN && INT_MAX
-#include "cmddata.h"
 #include "util.h"
 #include "cmdmain.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"       // for show graph controls
 #include "graph.h"    // for graph data
 #include "cmdparser.h"// already included in cmdmain.h
 
 // High frequency commands
 //-----------------------------------------------------------------------------
 
+#include "cmdhf.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "util.h"
 #include "ui.h"
 #include "iso14443crc.h"
 #include "parity.h"
 #include "cmdmain.h"
 #include "cmdparser.h"
-#include "cmdhf.h"
 #include "cmdhf14a.h"
 #include "cmdhf14b.h"
 #include "cmdhf15.h"
 
 #include "util.h"
 #include "util_posix.h"
 #include "iso14443crc.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "common.h"
 
 // High frequency ISO14443B commands
 //-----------------------------------------------------------------------------
 
+#include "cmdhf14b.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <string.h>
 #include <stdint.h>
 #include "iso14443crc.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "graph.h"
 #include "util.h"
 #include "ui.h"
 #include "cmdparser.h"
-#include "cmdhf14b.h"
 #include "cmdmain.h"
 #include "cmdhf14a.h"
 
 
 #ifndef CMDHF14B_H__
 #define CMDHF14B_H__
 
+#include <stdbool.h>
+
 int CmdHF14B(const char *Cmd);
 int CmdHF14BList(const char *Cmd);
 int CmdHF14BInfo(const char *Cmd);
 
 // the client. Signal Processing & decoding is done on the pc. This is the slowest
 // variant, but offers the possibility to analyze the waveforms directly. 
 
+#include "cmdhf15.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdint.h>
 
-#include "proxmark3.h"
+#include "comms.h"
 #include "graph.h"
 #include "ui.h"
 #include "util.h"
 #include "cmdparser.h"
-#include "cmdhf15.h"
 #include "iso15693tools.h"
 #include "cmdmain.h"
 
 
 #ifndef CMDHF15_H__
 #define CMDHF15_H__
 
+#include <stdbool.h>
+
 int CmdHF15(const char *Cmd);
 
 int CmdHF15Demod(const char *Cmd);
 
 #include <stdio.h>
 #include "util.h"
 #include "util_posix.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "common.h"
 
 #include <sys/stat.h>
 #include <ctype.h>
 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "cmdhficlass.h"
 
 // High frequency Legic commands
 //-----------------------------------------------------------------------------
 
+#include "cmdhflegic.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
-#include "cmdhflegic.h"
 #include "cmdmain.h"
 #include "util.h"
+
 static int CmdHelp(const char *Cmd);
 
 static command_t CommandTable[] = 
 
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <ctype.h>\r
-#include "proxmark3.h"\r
+#include "comms.h"\r
 #include "cmdmain.h"\r
 #include "cmdhfmfhard.h"\r
 #include "parity.h"\r
 
 #include <locale.h>
 #include <math.h>
 #include "proxmark3.h"
+#include "comms.h"
 #include "cmdmain.h"
 #include "ui.h"
 #include "util.h"
 
 
 #include <stdint.h>
 #include <stdio.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "usb_cmd.h"
 #include "cmdmain.h"
 #include "ui.h"
 
 // High frequency Topaz (NFC Type 1) commands
 //-----------------------------------------------------------------------------
 
+#include "cmdhftopaz.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include "cmdmain.h"
 #include "cmdparser.h"
-#include "cmdhftopaz.h"
 #include "cmdhf14a.h"
 #include "ui.h"
 #include "mifare.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "iso14443crc.h"
 #include "protocols.h"
 
 
 // Hardware commands
 //-----------------------------------------------------------------------------
 
+#include "cmdhw.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 #include "ui.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "cmdparser.h"
-#include "cmdhw.h"
 #include "cmdmain.h"
 #include "cmddata.h"
 
 
 // Low frequency commands
 //-----------------------------------------------------------------------------
 
+#include "cmdlf.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
-#include "proxmark3.h"
-#include "cmdlf.h"
+#include "comms.h"
 #include "lfdemod.h"     // for psk2TOpsk1
 #include "util.h"        // for parsing cli command utils
 #include "ui.h"          // for show graph controls
 
 // FSK2a, RF/50, 96 bits (complete)
 //-----------------------------------------------------------------------------
 
+#include "cmdlfawid.h"
+
 #include <string.h>
 #include <stdio.h>      // sscanf
-#include "proxmark3.h"  // Definitions, USB controls, etc
-#include "cmdlfawid.h"
+#include "comms.h"      // Definitions, USB controls, etc
 #include "ui.h"         // PrintAndLog
 #include "cmdparser.h"  // CmdsParse, CmdsHelp
 #include "lfdemod.h"    // parityTest +
 
 //-----------------------------------------------------------------------------
 // Low frequency COTAG commands
 //-----------------------------------------------------------------------------
+
+#include "cmdlfcotag.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmddata.h"
-#include "cmdlfcotag.h"
 #include "lfdemod.h"
 #include "usb_cmd.h"
 #include "cmdmain.h"
 
 // Low frequency EM4x commands
 //-----------------------------------------------------------------------------
 
+#include "cmdlfem4x.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
-#include "cmdlfem4x.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 #include <stdio.h>
 #include <inttypes.h>
 #include <string.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"         // for PrintAndLog
 #include "util.h"
 #include "cmdparser.h"
 
 // Low frequency HID commands (known)
 //-----------------------------------------------------------------------------
 
+#include "cmdlfhid.h"
+
 #include <stdio.h>
 #include <string.h>
-#include "cmdlfhid.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "graph.h"
 #include "cmdparser.h"
 
 // Low frequency Hitag support
 //-----------------------------------------------------------------------------
 
+#include "cmdlfhitag.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "cmdparser.h"
 #include "common.h"
 
 // PSK1, rf/32, 64 or 224 bits (known)
 //-----------------------------------------------------------------------------
 
+#include "cmdlfindala.h"
+
 #include <stdio.h>
 #include <string.h>
-#include "cmdlfindala.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "graph.h"
 #include "cmdparser.h"
 
 // FSK2a, rf/64, 64 bits (complete)
 //-----------------------------------------------------------------------------
 
+#include "cmdlfio.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <inttypes.h>
 #include <limits.h>
-#include "cmdlfio.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "graph.h"
 #include "ui.h"
 #include "cmdparser.h"
 
 //-----------------------------------------------------------------------------
 
 #include "cmdlfjablotron.h"
+
 #include <string.h>
 #include <inttypes.h>
 #include <stdbool.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency Honeywell NexWatch tag commands
 // PSK1 RF/16, RF/2, 128 bits long (known)
 //-----------------------------------------------------------------------------
+
+#include "cmdlfnexwatch.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
 #include <stdbool.h>
-#include "cmdlfnexwatch.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency Noralsy tag commands
 // ASK/Manchester, STT, RF/32, 96 bits long (some bits unknown)
 //-----------------------------------------------------------------------------
+
 #include "cmdlfnoralsy.h"
+
 #include <string.h>
 #include <inttypes.h>
 #include <math.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency Stanley/PAC tag commands
 // NRZ, RF/32, 128 bits long (unknown cs)
 //-----------------------------------------------------------------------------
+
 #include "cmdlfpac.h"
+
 #include <string.h>
 #include <inttypes.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 //-----------------------------------------------------------------------------
 // Low frequency PCF7931 commands
 //-----------------------------------------------------------------------------
+
+#include "cmdlfpcf7931.h"
+
 #include <stdio.h>
 #include <string.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 #include "cmddata.h"
 #include "cmdmain.h"
 #include "cmdlf.h"
-#include "cmdlfpcf7931.h"
 
 static int CmdHelp(const char *Cmd);
 
 
 #ifndef CMDLFPCF7931_H__
 #define CMDLFPCF7931_H__
 
+#include <stdint.h>
+
 struct pcf7931_config{
        uint8_t Pwd[7];
        uint16_t InitDelay;
 
 // Low frequency Presco tag commands
 // ASK/Manchester, rf/32, 128 bits (complete)
 //-----------------------------------------------------------------------------
+
+#include "cmdlfpresco.h"
+
 #include <string.h>
 #include <inttypes.h>
 #include <stdio.h>
-#include "cmdlfpresco.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency Farpoint / Pyramid tag commands
 // FSK2a, rf/50, 128 bits (complete)
 //-----------------------------------------------------------------------------
+
+#include "cmdlfpyramid.h"
+
 #include <string.h>
 #include <inttypes.h>
 #include <stdio.h>
-#include "cmdlfpyramid.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency Securakey tag commands
 // ASK/Manchester, RF/40, 96 bits long (unknown cs)
 //-----------------------------------------------------------------------------
+
 #include "cmdlfsecurakey.h"
+
 #include <string.h>
 #include <inttypes.h>
 #include <math.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 // Low frequency T55xx commands\r
 //-----------------------------------------------------------------------------\r
 \r
+#include "cmdlft55xx.h"\r
+\r
 #include <stdio.h>\r
 #include <string.h>\r
 #include <inttypes.h>\r
 #include <ctype.h>\r
 #include <time.h>\r
-#include "proxmark3.h"\r
+#include "comms.h"\r
 #include "ui.h"\r
 #include "graph.h"\r
 #include "cmdmain.h"\r
 #include "cmdparser.h"\r
 #include "cmddata.h"\r
 #include "cmdlf.h"\r
-#include "cmdlft55xx.h"\r
 #include "util.h"\r
 #include "lfdemod.h"\r
 #include "cmdhf14a.h" //for getTagInfo\r
 
 #ifndef CMDLFT55XX_H__\r
 #define CMDLFT55XX_H__\r
 \r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
 typedef struct {\r
        uint32_t bl1;\r
        uint32_t bl2; \r
 
 #include <stdlib.h>
 #include <inttypes.h>
 #include "crc16.h"
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "graph.h"
 #include "cmdparser.h"
 
 // Low frequency Viking tag commands (AKA FDI Matalec Transit)
 // ASK/Manchester, RF/32, 64 bits (complete)
 //-----------------------------------------------------------------------------
+
+#include "cmdlfviking.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
-#include "proxmark3.h"
-#include "cmdlfviking.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
 
 #include <stdio.h>
 #include <string.h>
-#include "proxmark3.h"
+#include "comms.h"
 #include "ui.h"
 #include "util.h"
 #include "graph.h"
 
   return CommandTable;
 }
 
-int CmdHelp(const char *Cmd)
+static int CmdHelp(const char *Cmd)
 {
   CmdsHelp(CommandTable);
   return 0;
 }
 
-int CmdQuit(const char *Cmd)
+static int CmdQuit(const char *Cmd)
 {
   return 99;
 }
 
 #ifndef CMDMAIN_H__
 #define CMDMAIN_H__
 
-#include <stdint.h>
-#include <stddef.h>
-#include "usb_cmd.h"
 #include "cmdparser.h"
-#include "comms.h"
-
 
 extern int CommandReceived(char *Cmd);
 extern command_t* getTopLevelCommandTable();
 
 // Code for communicating with the proxmark3 hardware.
 //-----------------------------------------------------------------------------
 
-#include <pthread.h>
-
 #include "comms.h"
+
+#include <pthread.h>
+#ifdef __linux__
+#include <unistd.h>            // for unlink()
+#endif
 #include "uart.h"
 #include "ui.h"
 #include "common.h"
 #include "util_posix.h"
 
-// Declare globals.
 
 // Serial port that we are communicating with the PM3 on.
-static serial_port sp;
+static serial_port sp = NULL;
+static char *serial_port_name = NULL;
 
 // If TRUE, then there is no active connection to the PM3, and we will drop commands sent.
 static bool offline;
 
+typedef struct {
+       bool run; // If TRUE, continue running the uart_communication thread
+       bool block_after_ACK; // if true, block after receiving an ACK package
+} communication_arg_t;
+
+static communication_arg_t conn;
+static pthread_t USB_communication_thread;
+
 // Transmit buffer.
-// TODO: Use locks and execute this on the main thread, rather than the receiver
-// thread.  Running on the main thread means we need to be careful in the
-// flasher, as it means SendCommand is no longer async, and can't be used as a
-// buffer for a pending command when the connection is re-established.
-static UsbCommand txcmd;
-volatile static bool txcmd_pending = false;
+static UsbCommand txBuffer;
+static bool txBuffer_pending = false;
+static pthread_mutex_t txBufferMutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER;
 
 // Used by UsbReceiveCommand as a ring buffer for messages that are yet to be
 // processed by a command handler (WaitForResponse{,Timeout})
-static UsbCommand cmdBuffer[CMD_BUFFER_SIZE];
+static UsbCommand rxBuffer[CMD_BUFFER_SIZE];
 
 // Points to the next empty position to write to
 static int cmd_head = 0;
 // Points to the position of the last unread command
 static int cmd_tail = 0;
 
-// to lock cmdBuffer operations from different threads
-static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER;
+// to lock rxBuffer operations from different threads
+static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER;
 
 // These wrappers are required because it is not possible to access a static
 // global variable outside of the context of a single file.
        return offline;
 }
 
-bool OpenProxmark(char *portname, bool waitCOMPort, int timeout) {
-       if (!waitCOMPort) {
-               sp = uart_open(portname);
-       } else {
-               printf("Waiting for Proxmark to appear on %s ", portname);
-               fflush(stdout);
-               int openCount = 0;
-               do {
-                       sp = uart_open(portname);
-                       msleep(1000);
-                       printf(".");
-                       fflush(stdout);
-               } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT));
-               printf("\n");
-       }
-
-       // check result of uart opening
-       if (sp == INVALID_SERIAL_PORT) {
-               printf("ERROR: invalid serial port\n");
-               return false;
-       } else if (sp == CLAIMED_SERIAL_PORT) {
-               printf("ERROR: serial port is claimed by another process\n");
-               return false;
-       } else {
-               return true;
-       }
-}
-
-void CloseProxmark(void) {
-       uart_close(sp);
-}
-
 void SendCommand(UsbCommand *c) {
        #ifdef COMMS_DEBUG
        printf("Sending %04x cmd\n", c->cmd);
                PrintAndLog("Sending bytes to proxmark failed - offline");
                return;
     }
+
+       pthread_mutex_lock(&txBufferMutex);
        /**
-       The while-loop below causes hangups at times, when the pm3 unit is unresponsive
-       or disconnected. The main console thread is alive, but comm thread just spins here.
-       Not good.../holiman
+       This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, 
+       but comm thread just spins here. Not good.../holiman
        **/
-       while(txcmd_pending);
+       while (txBuffer_pending) {
+               pthread_cond_wait(&txBufferSig, &txBufferMutex); // wait for communication thread to complete sending a previous commmand
+       }
+
+       txBuffer = *c;
+       txBuffer_pending = true;
+       pthread_cond_signal(&txBufferSig); // tell communication thread that a new command can be send
+
+       pthread_mutex_unlock(&txBufferMutex);
 
-       txcmd = *c;
-       txcmd_pending = true;
 }
 
 
 void clearCommandBuffer()
 {
        //This is a very simple operation
-       pthread_mutex_lock(&cmdBufferMutex);
+       pthread_mutex_lock(&rxBufferMutex);
        cmd_tail = cmd_head;
-       pthread_mutex_unlock(&cmdBufferMutex);
+       pthread_mutex_unlock(&rxBufferMutex);
 }
 
 /**
  * @brief storeCommand stores a USB command in a circular buffer
  * @param UC
  */
-void storeCommand(UsbCommand *command)
+static void storeCommand(UsbCommand *command)
 {
-       pthread_mutex_lock(&cmdBufferMutex);
+       pthread_mutex_lock(&rxBufferMutex);
        if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail)
        {
                // If these two are equal, we're about to overwrite in the
        }
 
        // Store the command at the 'head' location
-       UsbCommand* destination = &cmdBuffer[cmd_head];
+       UsbCommand* destination = &rxBuffer[cmd_head];
        memcpy(destination, command, sizeof(UsbCommand));
 
        cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap
-       pthread_mutex_unlock(&cmdBufferMutex);
+       pthread_mutex_unlock(&rxBufferMutex);
 }
 
 
  * @param response location to write command
  * @return 1 if response was returned, 0 if nothing has been received
  */
-int getCommand(UsbCommand* response)
+static int getCommand(UsbCommand* response)
 {
-       pthread_mutex_lock(&cmdBufferMutex);
+       pthread_mutex_lock(&rxBufferMutex);
        //If head == tail, there's nothing to read, or if we just got initialized
        if (cmd_head == cmd_tail){
-               pthread_mutex_unlock(&cmdBufferMutex);
+               pthread_mutex_unlock(&rxBufferMutex);
                return 0;
        }
 
        //Pick out the next unread command
-       UsbCommand* last_unread = &cmdBuffer[cmd_tail];
+       UsbCommand* last_unread = &rxBuffer[cmd_tail];
        memcpy(response, last_unread, sizeof(UsbCommand));
        //Increment tail - this is a circular buffer, so modulo buffer size
        cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE;
 
-       pthread_mutex_unlock(&cmdBufferMutex);
+       pthread_mutex_unlock(&rxBufferMutex);
        return 1;
 }
 
 }
 
 
-void
+static void
 #ifdef __has_attribute
 #if __has_attribute(force_align_arg_pointer)
 __attribute__((force_align_arg_pointer)) 
 #endif
 #endif
-*uart_receiver(void *targ) {
-       receiver_arg *conn = (receiver_arg*)targ;
+*uart_communication(void *targ) {
+       communication_arg_t *conn = (communication_arg_t*)targ;
        size_t rxlen;
-       uint8_t rx[sizeof(UsbCommand)];
-       uint8_t *prx = rx;
+       UsbCommand rx;
+       UsbCommand *prx = ℞
 
        while (conn->run) {
                rxlen = 0;
-               if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) {
+               bool ACK_received = false;
+               if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx-&rx), &rxlen) && rxlen) {
                        prx += rxlen;
-                       if (prx-rx < sizeof(UsbCommand)) {
+                       if (prx-&rx < sizeof(UsbCommand)) {
                                continue;
                        }
-                       UsbCommandReceived((UsbCommand*)rx);
+                       UsbCommandReceived(&rx);
+                       if (rx.cmd == CMD_ACK) {
+                               ACK_received = true;
+                       }
                }
-               prx = rx;
+               prx = ℞
+
+               
+               pthread_mutex_lock(&txBufferMutex);
 
-               if(txcmd_pending) {
-                       if (!uart_send(sp, (uint8_t*) &txcmd, sizeof(UsbCommand))) {
+               if (conn->block_after_ACK) {
+                       // if we just received an ACK, wait here until a new command is to be transmitted
+                       if (ACK_received) {
+                               while (!txBuffer_pending) {
+                                       pthread_cond_wait(&txBufferSig, &txBufferMutex);
+                               }
+                       }
+               }
+                               
+               if(txBuffer_pending) {
+                       if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) {
                                PrintAndLog("Sending bytes to proxmark failed");
                        }
-                       txcmd_pending = false;
+                       txBuffer_pending = false;
+                       pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
                }
+
+               pthread_mutex_unlock(&txBufferMutex);
        }
 
        pthread_exit(NULL);
 }
 
 
-
 /**
  * Data transfer from Proxmark to client. This method times out after
  * ms_timeout milliseconds.
        return false;
 }
 
+       
+bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) {
+       char *portname = (char *)port;
+       if (!wait_for_port) {
+               sp = uart_open(portname);
+       } else {
+               printf("Waiting for Proxmark to appear on %s ", portname);
+               fflush(stdout);
+               int openCount = 0;
+               do {
+                       sp = uart_open(portname);
+                       msleep(1000);
+                       printf(".");
+                       fflush(stdout);
+               } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT));
+               printf("\n");
+       }
+
+       // check result of uart opening
+       if (sp == INVALID_SERIAL_PORT) {
+               printf("ERROR: invalid serial port\n");
+               sp = NULL;
+               serial_port_name = NULL;
+               return false;
+       } else if (sp == CLAIMED_SERIAL_PORT) {
+               printf("ERROR: serial port is claimed by another process\n");
+               sp = NULL;
+               serial_port_name = NULL;
+               return false;
+       } else {
+               // start the USB communication thread
+               serial_port_name = portname;
+               conn.run = true;
+               conn.block_after_ACK = flash_mode;
+               pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
+               return true;
+       }
+}
+
+
+void CloseProxmark(void) {
+       conn.run = false;
+       pthread_join(USB_communication_thread, NULL);
+       uart_close(sp);
+#ifdef __linux__
+       // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/*
+       if (serial_port_name) {
+               unlink(serial_port_name);
+       }
+#endif
+}
+
 
 /**
  * Waits for a certain response type. This method waits for a maximum of
 
 #define CMD_BUFFER_SIZE 50
 #endif
 
-typedef struct {
-       // If TRUE, continue running the uart_receiver thread
-       bool run;
-
-       // Lock around serial port receives
-       pthread_mutex_t recv_lock;
-} receiver_arg;
-
-
 void SetOffline(bool new_offline);
 bool IsOffline();
 
-bool OpenProxmark(char *portname, bool waitCOMPort, int timeout);
+bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode);
 void CloseProxmark(void);
 
 void SendCommand(UsbCommand *c);
 
-void *uart_receiver(void *targ);
 void clearCommandBuffer();
 bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning);
 bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
 
 #include "elf.h"
 #include "proxendian.h"
 #include "usb_cmd.h"
-#include "uart.h"
-
-void SendCommand(UsbCommand* txcmd);
-void ReceiveCommand(UsbCommand* rxcmd);
-
-serial_port sp;
+#include "comms.h"
 
 #define FLASH_START            0x100000
 #define FLASH_SIZE             (256*1024)
        EV_CURRENT
 };
 
-void CloseProxmark(const char *serial_port_name) {
-       // Clean up the port
-       uart_close(sp);
-       // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/*
-       unlink(serial_port_name);
-}
-
-bool OpenProxmark(size_t i, const char *serial_port_name) {
-       sp = uart_open(serial_port_name);
-       if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) {
-               //poll once a second
-               return false;
-       }
-
-       return true;
-}
 
 // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
 // unaligned segments if needed
 }
 
 // Load an ELF file and prepare it for flashing
-int flash_load(flash_file_t *ctx, const char *name, int can_write_bl)
+int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl)
 {
        FILE *fd = NULL;
        Elf32_Ehdr ehdr;
        c.cmd = CMD_DEVICE_INFO;
        SendCommand(&c);
        UsbCommand resp;
-       ReceiveCommand(&resp);
+       WaitForResponse(CMD_UNKNOWN, &resp);  // wait for any response. No timeout.
 
        // Three outcomes:
        // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
                }
 
                msleep(100);
-               CloseProxmark(serial_port_name);
-
-               fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name);
-               do {
-                       sleep(1);
-                       fprintf(stderr, ".");
-               } while (!OpenProxmark(0, serial_port_name));
-
-               fprintf(stderr," Found.\n");
+               CloseProxmark();
 
-               return 0;
+               bool opened = OpenProxmark(serial_port_name, true, 120, true);   // wait for 2 minutes
+               if (opened) {
+                       fprintf(stderr," Found.\n");
+                       return 0;
+               } else {
+                       fprintf(stderr,"Error: Proxmark not found.\n");
+                       return -1;
+               }
        }
 
        fprintf(stderr, "Error: Unknown Proxmark mode\n");
 static int wait_for_ack(void)
 {
        UsbCommand ack;
-       ReceiveCommand(&ack);
+       WaitForResponse(CMD_UNKNOWN, &ack);
        if (ack.cmd != CMD_ACK) {
                printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd);
                return -1;
 
        memset(block_buf, 0xFF, BLOCK_SIZE);
        memcpy(block_buf, data, length);
-  UsbCommand c;
+       UsbCommand c;
        c.cmd = CMD_FINISH_WRITE;
        c.arg[0] = address;
        memcpy(c.d.asBytes, block_buf, length);
-  SendCommand(&c);
-  return wait_for_ack();
+       SendCommand(&c);
+       return wait_for_ack();
 }
 
 // Write a file's segments to Flash
 
 #define __FLASH_H__
 
 #include <stdint.h>
-#include "elf.h"
-#include "uart.h"
+#include <stdbool.h>
 
 typedef struct {
        void *data;
        flash_seg_t *segments;
 } flash_file_t;
 
-int flash_load(flash_file_t *ctx, const char *name, int can_write_bl);
+int flash_load(flash_file_t *ctx, const char *name, bool can_write_bl);
 int flash_start_flashing(int enable_bl_writes, char *serial_port_name);
 int flash_write(flash_file_t *ctx);
 void flash_free(flash_file_t *ctx);
 int flash_stop_flashing(void);
-void CloseProxmark(const char *serial_port_name);
-bool OpenProxmark(size_t i, const char *serial_port_name);
-
-extern serial_port sp;
 #endif
 
 
 #include <stdlib.h>
 #include <string.h>
 #include <inttypes.h>
+#include <pthread.h>
 #include "proxmark3.h"
 #include "util.h"
 #include "util_posix.h"
 #include "flash.h"
-#include "uart.h"
+#include "comms.h"
 #include "usb_cmd.h"
 
-#ifdef _WIN32
-# define unlink(x)
-#else
-# include <unistd.h>
-#endif
 
 void cmd_debug(UsbCommand* UC) {
   //  Debug
   printf("...\n");
 }
 
-void SendCommand(UsbCommand* txcmd) {
-//  printf("send: ");
-//  cmd_debug(txcmd);
-  if (!uart_send(sp,(uint8_t*)txcmd,sizeof(UsbCommand))) {
-    printf("Sending bytes to proxmark failed\n");
-    exit(1);
-  }
-}
-
-void ReceiveCommand(UsbCommand* rxcmd) {
-  uint8_t* prxcmd = (uint8_t*)rxcmd;
-  uint8_t* prx = prxcmd;
-  size_t rxlen;
-  while (true) {
-    if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) {
-      prx += rxlen;
-      if ((prx-prxcmd) >= sizeof(UsbCommand)) {
-        return;
-      }
-    }
-  }
-}
-
 static void usage(char *argv0)
 {
        fprintf(stderr, "Usage:   %s <port> [-b] image.elf [image.elf...]\n\n", argv0);
 
 int main(int argc, char **argv)
 {
-       int can_write_bl = 0;
+       int can_write_bl = false;
        int num_files = 0;
        int res;
        flash_file_t files[MAX_FILES];
        for (int i = 2; i < argc; i++) {
                if (argv[i][0] == '-') {
                        if (!strcmp(argv[i], "-b")) {
-                               can_write_bl = 1;
+                               can_write_bl = true;
                        } else {
                                usage(argv[0]);
                                return -1;
 
        char* serial_port_name = argv[1];
 
-       fprintf(stderr,"Waiting for Proxmark to appear on %s", serial_port_name);
-       do {
-               msleep(1000);
-               fprintf(stderr, ".");
-       } while (!OpenProxmark(0, serial_port_name));
-       fprintf(stderr," Found.\n");
+       if (!OpenProxmark(serial_port_name, true, 120, true)) {   // wait for 2 minutes
+               fprintf(stderr, "Could not find Proxmark on %s.\n\n", serial_port_name);
+               return -1;
+       } else {
+               fprintf(stderr," Found.\n");
+       }
 
        res = flash_start_flashing(can_write_bl, serial_port_name);
        if (res < 0)
        if (res < 0)
                return -1;
 
-       CloseProxmark(serial_port_name);
+       // Stop the command thread.
+       CloseProxmark();
 
        fprintf(stderr, "All done.\n\n");
        fprintf(stderr, "Have a nice day!\n");
 
 #include <pthread.h>\r
 \r
 #include "crapto1/crapto1.h"\r
-#include "proxmark3.h"\r
+#include "comms.h"\r
 #include "usb_cmd.h"\r
 #include "cmdmain.h"\r
 #include "ui.h"\r
 
 // Main binary
 //-----------------------------------------------------------------------------
 
+#include "proxmark3.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 
-#include "proxmark3.h"
 #include "util_posix.h"
 #include "proxgui.h"
 #include "cmdmain.h"
 #include "cmdparser.h"
 #include "cmdhw.h"
 #include "whereami.h"
-
+#include "comms.h"
 
 void
 #ifdef __has_attribute
 #endif
 #endif
 main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) {
-       receiver_arg conn;
        char *cmd = NULL;
-       pthread_t reader_thread;
        bool execCommand = (script_cmd != NULL);
        bool stdinOnPipe = !isatty(STDIN_FILENO);
 
-       memset(&conn, 0, sizeof(receiver_arg));
-
        if (usb_present) {
-               conn.run = true;
                SetOffline(false);
-               pthread_create(&reader_thread, NULL, &uart_receiver, &conn);
                // cache Version information now:
                CmdVersion(NULL);
        } else {
        write_history(".history");
 
        if (usb_present) {
-               conn.run = false;
-               pthread_join(reader_thread, NULL);
+               CloseProxmark();
        }
        
        if (script_file) {
        set_my_executable_path();
 
        // try to open USB connection to Proxmark
-       usb_present = OpenProxmark(argv[1], waitCOMPort, 20);
+       usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false);
 
 #ifdef HAVE_GUI
 #ifdef _WIN32
 
 extern "C" {
 #endif
 
-void SendCommand(UsbCommand *c);
 const char *get_my_executable_path(void);
 const char *get_my_executable_directory(void);
 void main_loop(char *script_cmds_file, char *script_cmd, bool usb_present);
 
 #include <lualib.h>
 #include <lauxlib.h>
 #include "proxmark3.h"
+#include "comms.h"
 #include "usb_cmd.h"
 #include "cmdmain.h"
 #include "util.h"