1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2009 Michael Gernoth <michael at gernoth.net> 
   3 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   5 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   6 // at your option, any later version. See the LICENSE.txt file for the text of 
   8 //----------------------------------------------------------------------------- 
   9 // Code for communicating with the proxmark3 hardware. 
  10 //----------------------------------------------------------------------------- 
  24 #include "util_darwin.h" 
  25 #include "util_posix.h" 
  28 // Serial port that we are communicating with the PM3 on. 
  29 static serial_port sp 
= NULL
; 
  30 static char *serial_port_name 
= NULL
; 
  32 // If TRUE, then there is no active connection to the PM3, and we will drop commands sent. 
  36         bool run
; // If TRUE, continue running the uart_communication thread 
  37 } communication_arg_t
; 
  39 static communication_arg_t conn
; 
  40 static pthread_t USB_communication_thread
; 
  43 static UsbCommand txBuffer
; 
  44 static bool txBuffer_pending 
= false; 
  45 static pthread_mutex_t txBufferMutex 
= PTHREAD_MUTEX_INITIALIZER
; 
  46 static pthread_cond_t txBufferSig 
= PTHREAD_COND_INITIALIZER
; 
  48 // Used by UsbReceiveCommand as a ring buffer for messages that are yet to be 
  49 // processed by a command handler (WaitForResponse{,Timeout}) 
  50 #define CMD_BUFFER_SIZE 50 
  51 #define CMD_BUFFER_CHECK_TIME 10 // maximum time (in ms) to wait in getCommand() 
  53 static UsbCommand rxBuffer
[CMD_BUFFER_SIZE
]; 
  55 // Points to the next empty position to write to 
  56 static int cmd_head 
= 0; 
  58 // Points to the position of the last unread command 
  59 static int cmd_tail 
= 0; 
  61 // to lock rxBuffer operations from different threads 
  62 static pthread_mutex_t rxBufferMutex 
= PTHREAD_MUTEX_INITIALIZER
; 
  63 static pthread_cond_t rxBufferSig 
= PTHREAD_COND_INITIALIZER
; 
  65 // These wrappers are required because it is not possible to access a static 
  66 // global variable outside of the context of a single file. 
  68 void SetOffline(bool new_offline
) { 
  69         offline 
= new_offline
; 
  76 void SendCommand(UsbCommand 
*c
) { 
  78         printf("Sending %04" PRIx64 
" cmd\n", c
->cmd
); 
  82                 PrintAndLog("Sending bytes to proxmark failed - offline"); 
  86         pthread_mutex_lock(&txBufferMutex
); 
  88         This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, 
  89         but comm thread just spins here. Not good.../holiman 
  91         while (txBuffer_pending
) { 
  92                 pthread_cond_wait(&txBufferSig
, &txBufferMutex
); // wait for communication thread to complete sending a previous commmand 
  96         txBuffer_pending 
= true; 
  97         pthread_cond_signal(&txBufferSig
); // tell communication thread that a new command can be send 
  99         pthread_mutex_unlock(&txBufferMutex
); 
 105  * @brief This method should be called when sending a new command to the pm3. In case any old 
 106  *  responses from previous commands are stored in the buffer, a call to this method should clear them. 
 107  *  A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which 
 108  *  operation. Right now we'll just have to live with this. 
 110 void clearCommandBuffer() { 
 111         //This is a very simple operation 
 112         pthread_mutex_lock(&rxBufferMutex
); 
 114         pthread_mutex_unlock(&rxBufferMutex
); 
 118  * @brief storeCommand stores a USB command in a circular buffer 
 121 static void storeCommand(UsbCommand 
*command
) { 
 122         pthread_mutex_lock(&rxBufferMutex
); 
 123         if ((cmd_head 
+ 1) % CMD_BUFFER_SIZE 
== cmd_tail
) { 
 124                 // If these two are equal, we're about to overwrite in the 
 126                 PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!"); 
 129         // Store the command at the 'head' location 
 130         UsbCommand
* destination 
= &rxBuffer
[cmd_head
]; 
 131         memcpy(destination
, command
, sizeof(UsbCommand
)); 
 133         cmd_head 
= (cmd_head 
+ 1) % CMD_BUFFER_SIZE
; //increment head and wrap 
 134         pthread_cond_signal(&rxBufferSig
); // tell main thread that a new command can be retreived 
 135         pthread_mutex_unlock(&rxBufferMutex
); 
 140  * @brief getCommand gets a command from an internal circular buffer. 
 141  * @param response location to write command 
 142  * @return 1 if response was returned, 0 if nothing has been received in time 
 144 static int getCommand(UsbCommand
* response
, uint32_t ms_timeout
) { 
 146         struct timespec end_time
; 
 147         clock_gettime(CLOCK_REALTIME
, &end_time
); 
 148         end_time
.tv_sec 
+= ms_timeout 
/ 1000; 
 149         end_time
.tv_nsec 
+= (ms_timeout 
% 1000) * 1000000; 
 150         if (end_time
.tv_nsec 
> 1000000000) { 
 151                 end_time
.tv_nsec 
-= 1000000000; 
 152                 end_time
.tv_sec 
+= 1; 
 154         pthread_mutex_lock(&rxBufferMutex
); 
 156         while (cmd_head 
== cmd_tail 
&& !res
) { 
 157                 res 
= pthread_cond_timedwait(&rxBufferSig
, &rxBufferMutex
, &end_time
); 
 159         if (res
) { // timeout 
 160                 pthread_mutex_unlock(&rxBufferMutex
); 
 164         // Pick out the next unread command 
 165         UsbCommand
* last_unread 
= &rxBuffer
[cmd_tail
]; 
 166         memcpy(response
, last_unread
, sizeof(UsbCommand
)); 
 167         // Increment tail - this is a circular buffer, so modulo buffer size 
 168         cmd_tail 
= (cmd_tail 
+ 1) % CMD_BUFFER_SIZE
; 
 170         pthread_mutex_unlock(&rxBufferMutex
); 
 175 //---------------------------------------------------------------------------------- 
 176 // Entry point into our code: called whenever we received a packet over USB. 
 177 // Handle debug commands directly, store all other commands in circular buffer. 
 178 //---------------------------------------------------------------------------------- 
 179 static void UsbCommandReceived(UsbCommand 
*UC
) { 
 181                 // First check if we are handling a debug message 
 182                 case CMD_DEBUG_PRINT_STRING
: { 
 183                         char s
[USB_CMD_DATA_SIZE
+1]; 
 184                         memset(s
, 0x00, sizeof(s
)); 
 185                         size_t len 
= MIN(UC
->arg
[0], USB_CMD_DATA_SIZE
); 
 186                         memcpy(s
, UC
->d
.asBytes
,len
); 
 187                         PrintAndLog("#db# %s", s
); 
 191                 case CMD_DEBUG_PRINT_INTEGERS
: { 
 192                         PrintAndLog("#db# %08x, %08x, %08x       \r\n", UC
->arg
[0], UC
->arg
[1], UC
->arg
[2]); 
 204 static bool receive_from_serial(serial_port sp
, uint8_t *rx_buf
, size_t len
, size_t *received_len
) { 
 205         size_t bytes_read 
= 0; 
 207         // we eventually need to call uart_receive several times because it may timeout in the middle of a transfer 
 208         while (uart_receive(sp
, rx_buf 
+ *received_len
, len 
- *received_len
, &bytes_read
) && bytes_read 
&& *received_len 
< len
) { 
 210                 if (bytes_read 
!= len 
- *received_len
) { 
 211                         printf("uart_receive() returned true but not enough bytes could be received. received: %zd, wanted to receive: %zd, already received before: %zd\n", 
 212                                 bytes_read
, len 
- *received_len
, *received_len
); 
 215                 *received_len 
+= bytes_read
; 
 218         return (*received_len 
== len
); 
 223 #ifdef __has_attribute 
 224 #if __has_attribute(force_align_arg_pointer) 
 225 __attribute__((force_align_arg_pointer
)) 
 228 *uart_communication(void *targ
) { 
 229         communication_arg_t 
*conn 
= (communication_arg_t
*)targ
; 
 230         uint8_t rx
[sizeof(UsbCommand
)]; 
 233         UsbCommand 
*command 
= (UsbCommand
*)rx
; 
 234         UsbResponse 
*response 
= (UsbResponse
*)rx
; 
 236 #if defined(__MACH__) && defined(__APPLE__) 
 237         disableAppNap("Proxmark3 polling UART"); 
 241                 bool ACK_received 
= false; 
 243                 size_t bytes_to_read 
= offsetof(UsbResponse
, d
);  // the fixed part of a new style UsbResponse. Otherwise this will be cmd and arg[0] (64 bit each) 
 244                 if (receive_from_serial(sp
, prx
, bytes_to_read
, &rxlen
)) { 
 246                         if (response
->cmd 
& CMD_VARIABLE_SIZE_FLAG
) { // new style response with variable size 
 248                                 PrintAndLog("received new style response %04" PRIx16 
", datalen = %zd, arg[0] = %08" PRIx32 
", arg[1] = %08" PRIx32 
", arg[2] = %08" PRIx32
, 
 249                                         response
->cmd
, response
->datalen
, response
->arg
[0], response
->arg
[1], response
->arg
[2]); 
 251                                 bytes_to_read 
= response
->datalen
; 
 252                                 if (receive_from_serial(sp
, prx
, bytes_to_read
, &rxlen
)) { 
 254                                         resp
.cmd 
= response
->cmd 
& ~CMD_VARIABLE_SIZE_FLAG
;  // remove the flag 
 255                                         resp
.arg
[0] = response
->arg
[0]; 
 256                                         resp
.arg
[1] = response
->arg
[1]; 
 257                                         resp
.arg
[2] = response
->arg
[2]; 
 258                                         memcpy(&resp
.d
.asBytes
, &response
->d
.asBytes
, response
->datalen
); 
 259                                         UsbCommandReceived(&resp
); 
 260                                         if (resp
.cmd 
== CMD_ACK
) { 
 264                         } else { // old style response uses same data structure as commands. Fixed size. 
 266                                 PrintAndLog("received old style response %016" PRIx64 
", arg[0] = %016" PRIx64
, command
->cmd
, command
->arg
[0]); 
 268                                 bytes_to_read 
= sizeof(UsbCommand
) - bytes_to_read
; 
 269                                 if (receive_from_serial(sp
, prx
, bytes_to_read
, &rxlen
)) { 
 270                                         UsbCommandReceived(command
); 
 271                                         if (command
->cmd 
== CMD_ACK
) { 
 278                 pthread_mutex_lock(&txBufferMutex
); 
 279                 // if we received an ACK the PM has done its job and waits for another command. 
 280                 // We therefore can wait here as well until a new command is to be transmitted. 
 281                 // The advantage is that the next command will be transmitted immediately without the need to wait for a receive timeout 
 283                         while (!txBuffer_pending
) { 
 284                                 pthread_cond_wait(&txBufferSig
, &txBufferMutex
); 
 287                 if (txBuffer_pending
) { 
 288                         if (!uart_send(sp
, (uint8_t*) &txBuffer
, sizeof(UsbCommand
))) { 
 289                                 PrintAndLog("Sending bytes to proxmark failed"); 
 291                         txBuffer_pending 
= false; 
 293                 pthread_cond_signal(&txBufferSig
); // tell main thread that txBuffer is empty 
 294                 pthread_mutex_unlock(&txBufferMutex
); 
 297 #if defined(__MACH__) && defined(__APPLE__) 
 307  * Data transfer from Proxmark to client. This method times out after 
 308  * ms_timeout milliseconds. 
 309  * @brief GetFromBigBuf 
 310  * @param dest Destination address for transfer 
 311  * @param bytes number of bytes to be transferred 
 312  * @param start_index offset into Proxmark3 BigBuf[] 
 313  * @param response struct to copy last command (CMD_ACK) into 
 314  * @param ms_timeout timeout in milliseconds 
 315  * @param show_warning display message after 2 seconds 
 316  * @return true if command was returned, otherwise false 
 318 bool GetFromBigBuf(uint8_t *dest
, int bytes
, int start_index
, UsbCommand 
*response
, size_t ms_timeout
, bool show_warning
) { 
 320         uint64_t start_time 
= msclock(); 
 322         UsbCommand c 
= {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K
, {start_index
, bytes
, 0}}; 
 326         if (response 
== NULL
) { 
 330         int bytes_completed 
= 0; 
 332                 if (msclock() - start_time 
> ms_timeout
) { 
 335                 if (msclock() - start_time 
> 2000 && show_warning
) { 
 336                         // 2 seconds elapsed (but this doesn't mean the timeout was exceeded) 
 337                         PrintAndLog("Waiting for a response from the proxmark..."); 
 338                         PrintAndLog("You can cancel this operation by pressing the pm3 button"); 
 339                         show_warning 
= false; 
 341                 if (getCommand(response
, CMD_BUFFER_CHECK_TIME
)) { 
 342                         if (response
->cmd 
== CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 343                                 int copy_bytes 
= MIN(bytes 
- bytes_completed
, response
->arg
[1]); 
 344                                 memcpy(dest 
+ response
->arg
[0], response
->d
.asBytes
, copy_bytes
); 
 345                                 bytes_completed 
+= copy_bytes
; 
 346                         } else if (response
->cmd 
== CMD_ACK
) { 
 356 bool GetFromFpgaRAM(uint8_t *dest
, int bytes
) { 
 358         uint64_t start_time 
= msclock(); 
 360         UsbCommand c 
= {CMD_HF_PLOT
, {0, 0, 0}}; 
 365         int bytes_completed 
= 0; 
 366         bool show_warning 
= true; 
 368                 if (msclock() - start_time 
> 2000 && show_warning
) { 
 369                         PrintAndLog("Waiting for a response from the proxmark..."); 
 370                         PrintAndLog("You can cancel this operation by pressing the pm3 button"); 
 371                         show_warning 
= false; 
 373                 if (getCommand(&response
, CMD_BUFFER_CHECK_TIME
)) { 
 374                         if (response
.cmd 
== CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K
) { 
 375                                 int copy_bytes 
= MIN(bytes 
- bytes_completed
, response
.arg
[1]); 
 376                                 memcpy(dest 
+ response
.arg
[0], response
.d
.asBytes
, copy_bytes
); 
 377                                 bytes_completed 
+= copy_bytes
; 
 378                         } else if (response
.cmd 
== CMD_ACK
) { 
 388 bool OpenProxmark(void *port
, bool wait_for_port
, int timeout
) { 
 389         char *portname 
= (char *)port
; 
 390         if (!wait_for_port
) { 
 391                 sp 
= uart_open(portname
); 
 393                 printf("Waiting for Proxmark to appear on %s ", portname
); 
 397                         sp 
= uart_open(portname
); 
 401                 } while (++openCount 
< timeout 
&& (sp 
== INVALID_SERIAL_PORT 
|| sp 
== CLAIMED_SERIAL_PORT
)); 
 405         // check result of uart opening 
 406         if (sp 
== INVALID_SERIAL_PORT
) { 
 407                 printf("ERROR: invalid serial port\n"); 
 409                 serial_port_name 
= NULL
; 
 411         } else if (sp 
== CLAIMED_SERIAL_PORT
) { 
 412                 printf("ERROR: serial port is claimed by another process\n"); 
 414                 serial_port_name 
= NULL
; 
 417                 // start the USB communication thread 
 418                 serial_port_name 
= portname
; 
 420                 pthread_create(&USB_communication_thread
, NULL
, &uart_communication
, &conn
); 
 426 void CloseProxmark(void) { 
 430         // In Android O and later, if an invalid pthread_t is passed to pthread_join, it calls fatal(). 
 431         // https://github.com/aosp-mirror/platform_bionic/blob/ed16b344e75f422fb36fbfd91fb30de339475880/libc/bionic/pthread_internal.cpp#L116-L128 
 433         // In Bionic libc, pthread_t is an integer. 
 435         if (USB_communication_thread 
!= 0) { 
 436                 pthread_join(USB_communication_thread
, NULL
); 
 439         // pthread_t is a struct on other libc, treat as an opaque memory reference 
 440         pthread_join(USB_communication_thread
, NULL
); 
 447         // Clean up our state 
 449         serial_port_name 
= NULL
; 
 451         memset(&USB_communication_thread
, 0, sizeof(pthread_t
)); 
 457  * Waits for a certain response type. This method waits for a maximum of 
 458  * ms_timeout milliseconds for a specified response command. 
 459  *@brief WaitForResponseTimeout 
 460  * @param cmd command to wait for, or CMD_UNKNOWN to take any command. 
 461  * @param response struct to copy received command into. 
 463  * @param show_warning display message after 2 seconds 
 464  * @return true if command was returned, otherwise false 
 466 bool WaitForResponseTimeoutW(uint32_t cmd
, UsbCommand
* response
, size_t ms_timeout
, bool show_warning
) { 
 471         printf("Waiting for %04x cmd\n", cmd
); 
 474         uint64_t start_time 
= msclock(); 
 476         if (response 
== NULL
) { 
 480         // Wait until the command is received 
 482                 if (ms_timeout 
!= -1 && msclock() > start_time 
+ ms_timeout
) { 
 485                 if (msclock() - start_time 
> 2000 && show_warning
) { 
 486                         // 2 seconds elapsed (but this doesn't mean the timeout was exceeded) 
 487                         PrintAndLog("Waiting for a response from the proxmark..."); 
 488                         PrintAndLog("You can cancel this operation by pressing the pm3 button"); 
 489                         show_warning 
= false; 
 491                 if (getCommand(response
, CMD_BUFFER_CHECK_TIME
)) { 
 492                         if (cmd 
== CMD_UNKNOWN 
|| response
->cmd 
== cmd
) { 
 501 bool WaitForResponseTimeout(uint32_t cmd
, UsbCommand
* response
, size_t ms_timeout
) { 
 502         return WaitForResponseTimeoutW(cmd
, response
, ms_timeout
, true); 
 505 bool WaitForResponse(uint32_t cmd
, UsbCommand
* response
) { 
 506         return WaitForResponseTimeoutW(cmd
, response
, -1, true);