From: pwpiwi Date: Sat, 31 Mar 2018 07:52:43 +0000 (+0200) Subject: USB comm: prepare for @micolous change (PR#463) (#587) X-Git-Tag: v3.1.0~59 X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/f5ecd97b15797e14e691bb6f3562ec1685c96bca?ds=sidebyside USB comm: prepare for @micolous change (PR#463) (#587) * move communication related code from proxmark3.c and cmdmain.c to new file comms.c * replace byte_t by uint8_t in uart_posix.c and uart_win32.c * move OpenProxmark() and CloseProxmark() from flasher.c to flash.c * move print_lock mutex including initializer to ui.c * minor changes in printing help texts * no changes in comms functionality yet --- diff --git a/client/Makefile b/client/Makefile index bf3c8d36..883f3b6f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -170,7 +170,8 @@ CMDSRCS = crapto1/crapto1.c\ cmdscript.c\ pm3_binlib.c\ pm3_bitlib.c\ - protocols.c + protocols.c\ + comms.c cpu_arch = $(shell uname -m) ifneq ($(findstring 86, $(cpu_arch)), ) diff --git a/client/cmdmain.c b/client/cmdmain.c index 8d9313f9..10948c97 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -34,15 +34,6 @@ unsigned int current_command = CMD_UNKNOWN; static int CmdHelp(const char *Cmd); static int CmdQuit(const char *Cmd); -//For storing command that are received from the device -#define CMD_BUFFER_SIZE 50 -static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; -//Points to the next empty position to write to -static int cmd_head;//Starts as 0 -//Points to the position of the last unread command -static int cmd_tail;//Starts as 0 -// to lock cmdBuffer operations from different threads -static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; static command_t CommandTable[] = { @@ -61,6 +52,7 @@ command_t* getTopLevelCommandTable() { return CommandTable; } + int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); @@ -72,113 +64,6 @@ int CmdQuit(const char *Cmd) return 99; } -/** - * @brief This method should be called when sending a new command to the pm3. In case any old - * responses from previous commands are stored in the buffer, a call to this method should clear them. - * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which - * operation. Right now we'll just have to live with this. - */ -void clearCommandBuffer() -{ - //This is a very simple operation - pthread_mutex_lock(&cmdBufferMutex); - cmd_tail = cmd_head; - pthread_mutex_unlock(&cmdBufferMutex); -} - -/** - * @brief storeCommand stores a USB command in a circular buffer - * @param UC - */ -void storeCommand(UsbCommand *command) -{ - pthread_mutex_lock(&cmdBufferMutex); - if( ( cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) - { - //If these two are equal, we're about to overwrite in the - // circular buffer. - PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); - } - //Store the command at the 'head' location - UsbCommand* destination = &cmdBuffer[cmd_head]; - memcpy(destination, command, sizeof(UsbCommand)); - - cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - pthread_mutex_unlock(&cmdBufferMutex); -} - - -/** - * @brief getCommand gets a command from an internal circular buffer. - * @param response location to write command - * @return 1 if response was returned, 0 if nothing has been received - */ -int getCommand(UsbCommand* response) -{ - pthread_mutex_lock(&cmdBufferMutex); - //If head == tail, there's nothing to read, or if we just got initialized - if(cmd_head == cmd_tail){ - pthread_mutex_unlock(&cmdBufferMutex); - return 0; - } - //Pick out the next unread command - UsbCommand* last_unread = &cmdBuffer[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); - return 1; -} - - -/** - * Waits for a certain response type. This method waits for a maximum of - * ms_timeout milliseconds for a specified response command. - *@brief WaitForResponseTimeout - * @param cmd command to wait for - * @param response struct to copy received command into. - * @param ms_timeout - * @return true if command was returned, otherwise false - */ -bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { - - UsbCommand resp; - - if (response == NULL) { - response = &resp; - } - - uint64_t start_time = msclock(); - - // Wait until the command is received - while (true) { - while(getCommand(response)) { - if(response->cmd == cmd){ - return true; - } - } - if (msclock() - start_time > ms_timeout) { - break; - } - if (msclock() - start_time > 2000 && show_warning) { - PrintAndLog("Waiting for a response from the proxmark..."); - PrintAndLog("You can cancel this operation by pressing the pm3 button"); - show_warning = false; - } - } - return false; -} - - -bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { - return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); -} - -bool WaitForResponse(uint32_t cmd, UsbCommand* response) { - return WaitForResponseTimeoutW(cmd, response, -1, true); -} - - //----------------------------------------------------------------------------- // Entry point into our code: called whenever the user types a command and // then presses Enter, which the full command line that they typed. @@ -187,38 +72,3 @@ int CommandReceived(char *Cmd) { return CmdsParse(CommandTable, Cmd); } - -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever we received a packet over USB -// that we weren't necessarily expecting, for example a debug print. -//----------------------------------------------------------------------------- -void UsbCommandReceived(UsbCommand *UC) -{ - switch(UC->cmd) { - // First check if we are handling a debug message - case CMD_DEBUG_PRINT_STRING: { - char s[USB_CMD_DATA_SIZE+1]; - memset(s, 0x00, sizeof(s)); - size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE); - memcpy(s,UC->d.asBytes,len); - PrintAndLog("#db# %s", s); - return; - } break; - - case CMD_DEBUG_PRINT_INTEGERS: { - PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]); - return; - } break; - - case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { - memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); - return; - } break; - - default: - storeCommand(UC); - break; - } - -} - diff --git a/client/cmdmain.h b/client/cmdmain.h index d39bc114..a833b41e 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -15,13 +15,10 @@ #include #include "usb_cmd.h" #include "cmdparser.h" +#include "comms.h" + -extern void UsbCommandReceived(UsbCommand *UC); extern int CommandReceived(char *Cmd); -extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); -extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); -extern bool WaitForResponse(uint32_t cmd, UsbCommand* response); -extern void clearCommandBuffer(); extern command_t* getTopLevelCommandTable(); #endif diff --git a/client/cmdparser.c b/client/cmdparser.c index 32508997..f4d3c404 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -8,12 +8,14 @@ // Command parser //----------------------------------------------------------------------------- +#include "cmdparser.h" + #include #include #include #include "ui.h" -#include "cmdparser.h" #include "proxmark3.h" +#include "comms.h" void CmdsHelp(const command_t Commands[]) diff --git a/client/comms.c b/client/comms.c new file mode 100644 index 00000000..5b8266fe --- /dev/null +++ b/client/comms.c @@ -0,0 +1,252 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#include + +#include "comms.h" +#include "uart.h" +#include "ui.h" +#include "common.h" +#include "data.h" +#include "util_posix.h" + +// Declare globals. + +// Serial port that we are communicating with the PM3 on. +serial_port sp; + +// If TRUE, then there is no active connection to the PM3, and we will drop commands sent. +bool offline; + +// 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; + +// 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]; + +// 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; + + +void SendCommand(UsbCommand *c) { + #if 0 + printf("Sending %d bytes\n", sizeof(UsbCommand)); + #endif + + if (offline) { + PrintAndLog("Sending bytes to proxmark failed - offline"); + return; + } + /** + 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 + **/ + while(txcmd_pending); + txcmd = *c; + txcmd_pending = true; +} + + +/** + * @brief This method should be called when sending a new command to the pm3. In case any old + * responses from previous commands are stored in the buffer, a call to this method should clear them. + * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which + * operation. Right now we'll just have to live with this. + */ +void clearCommandBuffer() +{ + //This is a very simple operation + pthread_mutex_lock(&cmdBufferMutex); + cmd_tail = cmd_head; + pthread_mutex_unlock(&cmdBufferMutex); +} + +/** + * @brief storeCommand stores a USB command in a circular buffer + * @param UC + */ +void storeCommand(UsbCommand *command) +{ + pthread_mutex_lock(&cmdBufferMutex); + if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) + { + // If these two are equal, we're about to overwrite in the + // circular buffer. + PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); + } + + // Store the command at the 'head' location + UsbCommand* destination = &cmdBuffer[cmd_head]; + memcpy(destination, command, sizeof(UsbCommand)); + + cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap + pthread_mutex_unlock(&cmdBufferMutex); +} + + +/** + * @brief getCommand gets a command from an internal circular buffer. + * @param response location to write command + * @return 1 if response was returned, 0 if nothing has been received + */ +int getCommand(UsbCommand* response) +{ + pthread_mutex_lock(&cmdBufferMutex); + //If head == tail, there's nothing to read, or if we just got initialized + if (cmd_head == cmd_tail){ + pthread_mutex_unlock(&cmdBufferMutex); + return 0; + } + + //Pick out the next unread command + UsbCommand* last_unread = &cmdBuffer[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); + return 1; +} + + +//----------------------------------------------------------------------------- +// Entry point into our code: called whenever we received a packet over USB +// that we weren't necessarily expecting, for example a debug print. +//----------------------------------------------------------------------------- +void UsbCommandReceived(UsbCommand *UC) +{ + switch(UC->cmd) { + // First check if we are handling a debug message + case CMD_DEBUG_PRINT_STRING: { + char s[USB_CMD_DATA_SIZE+1]; + memset(s, 0x00, sizeof(s)); + size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE); + memcpy(s,UC->d.asBytes,len); + PrintAndLog("#db# %s", s); + return; + } break; + + case CMD_DEBUG_PRINT_INTEGERS: { + PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]); + return; + } break; + + case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { + memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); + return; + } break; + + default: + storeCommand(UC); + break; + } + +} + + +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*uart_receiver(void *targ) { + receiver_arg *arg = (receiver_arg*)targ; + size_t rxlen; + uint8_t rx[sizeof(UsbCommand)]; + uint8_t *prx = rx; + + while (arg->run) { + rxlen = 0; + if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { + prx += rxlen; + if (prx-rx < sizeof(UsbCommand)) { + continue; + } + UsbCommandReceived((UsbCommand*)rx); + } + prx = rx; + + if(txcmd_pending) { + if (!uart_send(sp, (uint8_t*) &txcmd, sizeof(UsbCommand))) { + PrintAndLog("Sending bytes to proxmark failed"); + } + txcmd_pending = false; + } + } + + pthread_exit(NULL); + return NULL; +} + + +/** + * Waits for a certain response type. This method waits for a maximum of + * ms_timeout milliseconds for a specified response command. + *@brief WaitForResponseTimeout + * @param cmd command to wait for + * @param response struct to copy received command into. + * @param ms_timeout + * @return true if command was returned, otherwise false + */ +bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { + + UsbCommand resp; + + if (response == NULL) { + response = &resp; + } + + uint64_t start_time = msclock(); + + // Wait until the command is received + while (true) { + while(getCommand(response)) { + if(response->cmd == cmd){ + return true; + } + } + + if (msclock() - start_time > ms_timeout) { + break; + } + + if (msclock() - start_time > 2000 && show_warning) { + PrintAndLog("Waiting for a response from the proxmark..."); + PrintAndLog("You can cancel this operation by pressing the pm3 button"); + show_warning = false; + } + } + return false; +} + + +bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { + return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); +} + +bool WaitForResponse(uint32_t cmd, UsbCommand* response) { + return WaitForResponseTimeoutW(cmd, response, -1, true); +} + diff --git a/client/comms.h b/client/comms.h new file mode 100644 index 00000000..40576018 --- /dev/null +++ b/client/comms.h @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#ifndef COMMS_H_ +#define COMMS_H_ + +#include +#include + +#include "usb_cmd.h" +#include "uart.h" + +#ifndef CMD_BUFFER_SIZE +#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 SendCommand(UsbCommand *c); + +void *uart_receiver(void *targ); +void UsbCommandReceived(UsbCommand *UC); +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); +bool WaitForResponse(uint32_t cmd, UsbCommand* response); + +extern serial_port sp; +extern bool offline; + +#endif // COMMS_H_ diff --git a/client/flash.c b/client/flash.c index 7622e8a5..894095e7 100644 --- a/client/flash.c +++ b/client/flash.c @@ -20,11 +20,12 @@ #include "elf.h" #include "proxendian.h" #include "usb_cmd.h" +#include "uart.h" void SendCommand(UsbCommand* txcmd); void ReceiveCommand(UsbCommand* rxcmd); -void CloseProxmark(); -int OpenProxmark(size_t i); + +serial_port sp; // FIXME: what the fuckity fuck unsigned int current_command = CMD_UNKNOWN; @@ -44,6 +45,22 @@ static const uint8_t elf_ident[] = { 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); +} + +int 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 0; + } + return 1; +} + // Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent // unaligned segments if needed static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs) @@ -278,7 +295,7 @@ static int get_proxmark_state(uint32_t *state) { UsbCommand c; c.cmd = CMD_DEVICE_INFO; - SendCommand(&c); + SendCommand(&c); UsbCommand resp; ReceiveCommand(&resp); @@ -338,14 +355,14 @@ static int enter_bootloader(char *serial_port_name) SendCommand(&c); fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n"); } - msleep(100); - CloseProxmark(); + msleep(100); + CloseProxmark(serial_port_name); fprintf(stderr,"Waiting for Proxmark to reappear on %s",serial_port_name); - do { + do { sleep(1); fprintf(stderr, "."); - } while (!OpenProxmark(0)); + } while (!OpenProxmark(0, serial_port_name)); fprintf(stderr," Found.\n"); return 0; @@ -357,7 +374,7 @@ static int enter_bootloader(char *serial_port_name) static int wait_for_ack(void) { - UsbCommand ack; + UsbCommand ack; ReceiveCommand(&ack); if (ack.cmd != CMD_ACK) { printf("Error: Unexpected reply 0x%04" PRIx64 " (expected ACK)\n", ack.cmd); @@ -472,7 +489,7 @@ void flash_free(flash_file_t *ctx) // just reset the unit int flash_stop_flashing(void) { UsbCommand c = {CMD_HARDWARE_RESET}; - SendCommand(&c); - msleep(100); - return 0; + SendCommand(&c); + msleep(100); + return 0; } diff --git a/client/flash.h b/client/flash.h index 3e9f77a7..7f365924 100644 --- a/client/flash.h +++ b/client/flash.h @@ -11,6 +11,7 @@ #include #include "elf.h" +#include "uart.h" typedef struct { void *data; @@ -26,10 +27,13 @@ typedef struct { } flash_file_t; int flash_load(flash_file_t *ctx, const char *name, int can_write_bl); -int flash_start_flashing(int enable_bl_writes,char *serial_port_name); +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); +int OpenProxmark(size_t i, const char *serial_port_name); +extern serial_port sp; #endif diff --git a/client/flasher.c b/client/flasher.c index f257d994..2bb87df9 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -23,9 +23,6 @@ # include #endif -static serial_port sp; -static char* serial_port_name; - void cmd_debug(UsbCommand* UC) { // Debug printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand)); @@ -43,15 +40,15 @@ void cmd_debug(UsbCommand* UC) { void SendCommand(UsbCommand* txcmd) { // printf("send: "); // cmd_debug(txcmd); - if (!uart_send(sp,(byte_t*)txcmd,sizeof(UsbCommand))) { + if (!uart_send(sp,(uint8_t*)txcmd,sizeof(UsbCommand))) { printf("Sending bytes to proxmark failed\n"); exit(1); } } void ReceiveCommand(UsbCommand* rxcmd) { - byte_t* prxcmd = (byte_t*)rxcmd; - byte_t* prx = prxcmd; + 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)) { @@ -63,32 +60,17 @@ void ReceiveCommand(UsbCommand* rxcmd) { } } -void CloseProxmark() { - // 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); -} - -int OpenProxmark(size_t i) { - sp = uart_open(serial_port_name); - if (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT) { - //poll once a second - return 0; - } - return 1; -} - static void usage(char *argv0) { fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); - //Is the example below really true? /Martin - fprintf(stderr, "Example:\n\n\t %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0); - fprintf(stderr, "\nExample (Linux):\n\n\t %s /dev/ttyACM0 armsrc/obj/fullimage.elf\n", argv0); - fprintf(stderr, "\nNote (Linux): if the flasher gets stuck in 'Waiting for Proxmark to reappear on ',\n"); - fprintf(stderr, " you need to blacklist proxmark for modem-manager - see wiki for more details:\n"); - fprintf(stderr, " http://code.google.com/p/proxmark3/wiki/Linux\n\n"); + fprintf(stderr, "\nExample:\n\n\t %s "SERIAL_PORT_H" armsrc/obj/fullimage.elf\n", argv0); +#ifdef __linux__ + fprintf(stderr, "\nNote (Linux): if the flasher gets stuck at 'Waiting for Proxmark to reappear',\n"); + fprintf(stderr, " you may need to blacklist proxmark for modem-manager. v1.4.14 and later\n"); + fprintf(stderr, " include this configuration patch already. The change can be found at:\n"); + fprintf(stderr, " https://cgit.freedesktop.org/ModemManager/ModemManager/commit/?id=6e7ff47\n\n"); +#endif } #define MAX_FILES 4 @@ -126,16 +108,16 @@ int main(int argc, char **argv) } } - 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)); - fprintf(stderr," Found.\n"); + 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"); - res = flash_start_flashing(can_write_bl,serial_port_name); + res = flash_start_flashing(can_write_bl, serial_port_name); if (res < 0) return -1; @@ -155,7 +137,7 @@ int main(int argc, char **argv) if (res < 0) return -1; - CloseProxmark(); + CloseProxmark(serial_port_name); fprintf(stderr, "All done.\n\n"); fprintf(stderr, "Have a nice day!\n"); diff --git a/client/proxgui.h b/client/proxgui.h index 77bcbf01..5cad6e3a 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -30,7 +30,6 @@ extern int s_Buff[MAX_GRAPH_TRACE_LEN]; extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; extern int CommandFinished; -extern int offline; extern bool GridLocked; //Operations defined in data_operations diff --git a/client/proxmark3.c b/client/proxmark3.c index 1b64f68b..fc258609 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -28,79 +28,6 @@ #include "cmdhw.h" #include "whereami.h" -#ifdef _WIN32 -#define SERIAL_PORT_H "com3" -#else -#define SERIAL_PORT_H "/dev/ttyACM0" -#endif - -// a global mutex to prevent interlaced printing from different threads -pthread_mutex_t print_lock; - -static serial_port sp; -static UsbCommand txcmd; -volatile static bool txcmd_pending = false; - -void SendCommand(UsbCommand *c) { - #if 0 - printf("Sending %d bytes\n", sizeof(UsbCommand)); - #endif - - if (offline) { - PrintAndLog("Sending bytes to proxmark failed - offline"); - return; - } - /** - 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 - **/ - while(txcmd_pending); - txcmd = *c; - txcmd_pending = true; -} - -struct receiver_arg { - int run; -}; - -byte_t rx[sizeof(UsbCommand)]; -byte_t* prx = rx; - - -static void -#ifdef __has_attribute -#if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) -#endif -#endif -*uart_receiver(void *targ) { - struct receiver_arg *arg = (struct receiver_arg*)targ; - size_t rxlen; - - while (arg->run) { - rxlen = 0; - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen) && rxlen) { - prx += rxlen; - if (prx-rx < sizeof(UsbCommand)) { - continue; - } - UsbCommandReceived((UsbCommand*)rx); - } - prx = rx; - - if(txcmd_pending) { - if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) { - PrintAndLog("Sending bytes to proxmark failed"); - } - txcmd_pending = false; - } - } - - pthread_exit(NULL); - return NULL; -} - void #ifdef __has_attribute @@ -109,15 +36,17 @@ __attribute__((force_align_arg_pointer)) #endif #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { - struct receiver_arg rarg; + 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) { - rarg.run = 1; - pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); + conn.run = true; + pthread_create(&reader_thread, NULL, &uart_receiver, &conn); // cache Version information now: CmdVersion(NULL); } @@ -135,7 +64,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { read_history(".history"); - while(1) { + while (1) { // If there is a script file if (script_file) { @@ -207,7 +136,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { write_history(".history"); if (usb_present) { - rarg.run = 0; + conn.run = false; pthread_join(reader_thread, NULL); } @@ -257,9 +186,8 @@ static void set_my_executable_path(void) static void show_help(bool showFullHelp, char *command_line){ printf("syntax: %s [-h|-help|-m|-f|-flush|-w|-wait|-c|-command|-l|-lua] [cmd_script_file_name] [command][lua_script_name]\n", command_line); - printf("\tLinux example:'%s /dev/ttyACM0'\n", command_line); - printf("\tWindows example:'%s com3'\n\n", command_line); - + printf("\texample: %s "SERIAL_PORT_H"\n\n", command_line); + if (showFullHelp){ printf("help: <-h|-help> Dump all interactive command's help at once.\n"); printf("\t%s -h\n\n", command_line); @@ -287,7 +215,7 @@ int main(int argc, char* argv[]) { bool addLuaExec = false; char *script_cmds_file = NULL; char *script_cmd = NULL; - + if (argc < 2) { show_help(true, argv[0]); return 1; @@ -392,9 +320,6 @@ int main(int argc, char* argv[]) { usb_present = true; offline = 0; } - - // create a mutex to avoid interlacing print commands from our different threads - pthread_mutex_init(&print_lock, NULL); #ifdef HAVE_GUI #ifdef _WIN32 @@ -422,8 +347,5 @@ int main(int argc, char* argv[]) { uart_close(sp); } - // clean up mutex - pthread_mutex_destroy(&print_lock); - exit(0); } diff --git a/client/ui.c b/client/ui.c index dc122d2f..b0669a22 100644 --- a/client/ui.c +++ b/client/ui.c @@ -31,8 +31,7 @@ bool showDemod = true; static char *logfilename = "proxmark3.log"; #ifndef EXTERNAL_PRINTANDLOG -// Declared in proxmark3.c -extern pthread_mutex_t print_lock; +static pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER; void PrintAndLog(char *fmt, ...) { diff --git a/client/ui.h b/client/ui.h index 4049033d..28512ca9 100644 --- a/client/ui.h +++ b/client/ui.h @@ -23,7 +23,6 @@ void SetLogFilename(char *fn); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; -extern int offline; extern int flushAfterWrite; //buzzy extern bool GridLocked; extern bool showDemod; diff --git a/uart/uart.h b/uart/uart.h index fe75a683..3b563be2 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -39,7 +39,15 @@ #include #include -typedef unsigned char byte_t; +/* Used to substitute for an example serial port path on each platform. + */ +#ifdef _WIN32 +#define SERIAL_PORT_H "com3" +#elif __APPLE__ +#define SERIAL_PORT_H "/dev/tty.usbmodem*" +#else +#define SERIAL_PORT_H "/dev/ttyACM0" +#endif /* serial_port is declared as a void*, which you should cast to whatever type * makes sense to your connection method. Both the posix and win32 @@ -78,13 +86,13 @@ void uart_close(const serial_port sp); * partial read may have completed into the buffer by the corresponding * implementation, so pszRxLen should be checked to see if any data was written. */ -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); /* Sends a buffer to a given serial port. * pbtTx: A pointer to a buffer containing the data to send. * szTxLen: The amount of data to be sent. */ -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen); +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen); /* Sets the current speed of the serial port, in baud. */ diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 45e0d3d2..0e7f7f47 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -133,7 +133,7 @@ void uart_close(const serial_port sp) { free(sp); } -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; @@ -192,7 +192,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ return true; } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) { int32_t res; size_t szPos = 0; fd_set rfds; diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 121b2b51..b15e8786 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -107,11 +107,11 @@ void uart_close(const serial_port sp) { free(sp); } -bool uart_receive(const serial_port sp, byte_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) { +bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) { return ReadFile(((serial_port_windows*)sp)->hPort, pbtRx, pszMaxRxLen, (LPDWORD)pszRxLen, NULL); } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen) { +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t szTxLen) { DWORD dwTxLen = 0; return WriteFile(((serial_port_windows*)sp)->hPort, pbtTx, szTxLen, &dwTxLen, NULL); }