]> git.zerfleddert.de Git - proxmark3-svn/blame - client/comms.c
Always enable fast response mode (was enabled for flasher only)
[proxmark3-svn] / client / comms.c
CommitLineData
f5ecd97b 1//-----------------------------------------------------------------------------
2// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
3// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4//
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
7// the license.
8//-----------------------------------------------------------------------------
9// Code for communicating with the proxmark3 hardware.
10//-----------------------------------------------------------------------------
11
f5ecd97b 12#include "comms.h"
ad939de5 13
929b61c6 14#include <stdio.h>
ad939de5 15#include <pthread.h>
b8ed9975 16#include <inttypes.h>
17
577b1c27 18#if defined(__linux__) && !defined(NO_UNLINK)
929b61c6 19#include <unistd.h> // for unlink()
ad939de5 20#endif
f5ecd97b 21#include "uart.h"
22#include "ui.h"
23#include "common.h"
2a537311 24#include "util_darwin.h"
f5ecd97b 25#include "util_posix.h"
26
f5ecd97b 27
28// Serial port that we are communicating with the PM3 on.
ad939de5 29static serial_port sp = NULL;
30static char *serial_port_name = NULL;
f5ecd97b 31
32// If TRUE, then there is no active connection to the PM3, and we will drop commands sent.
61aaee35 33static bool offline;
f5ecd97b 34
ad939de5 35typedef struct {
36 bool run; // If TRUE, continue running the uart_communication thread
ad939de5 37} communication_arg_t;
38
39static communication_arg_t conn;
40static pthread_t USB_communication_thread;
41
f5ecd97b 42// Transmit buffer.
ad939de5 43static UsbCommand txBuffer;
44static bool txBuffer_pending = false;
45static pthread_mutex_t txBufferMutex = PTHREAD_MUTEX_INITIALIZER;
46static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER;
f5ecd97b 47
48// Used by UsbReceiveCommand as a ring buffer for messages that are yet to be
49// processed by a command handler (WaitForResponse{,Timeout})
b8ed9975 50#define CMD_BUFFER_SIZE 50
ad939de5 51static UsbCommand rxBuffer[CMD_BUFFER_SIZE];
f5ecd97b 52
53// Points to the next empty position to write to
54static int cmd_head = 0;
55
56// Points to the position of the last unread command
57static int cmd_tail = 0;
58
ad939de5 59// to lock rxBuffer operations from different threads
60static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER;
f5ecd97b 61
61aaee35 62// These wrappers are required because it is not possible to access a static
63// global variable outside of the context of a single file.
64
65void SetOffline(bool new_offline) {
66 offline = new_offline;
67}
68
69bool IsOffline() {
70 return offline;
71}
f5ecd97b 72
73void SendCommand(UsbCommand *c) {
61aaee35 74 #ifdef COMMS_DEBUG
75 printf("Sending %04x cmd\n", c->cmd);
f5ecd97b 76 #endif
77
78 if (offline) {
79 PrintAndLog("Sending bytes to proxmark failed - offline");
80 return;
929b61c6 81 }
ad939de5 82
83 pthread_mutex_lock(&txBufferMutex);
f5ecd97b 84 /**
929b61c6 85 This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive,
ad939de5 86 but comm thread just spins here. Not good.../holiman
f5ecd97b 87 **/
ad939de5 88 while (txBuffer_pending) {
89 pthread_cond_wait(&txBufferSig, &txBufferMutex); // wait for communication thread to complete sending a previous commmand
90 }
91
92 txBuffer = *c;
93 txBuffer_pending = true;
94 pthread_cond_signal(&txBufferSig); // tell communication thread that a new command can be send
95
96 pthread_mutex_unlock(&txBufferMutex);
818efbeb 97
f5ecd97b 98}
99
100
101/**
102 * @brief This method should be called when sending a new command to the pm3. In case any old
103 * responses from previous commands are stored in the buffer, a call to this method should clear them.
104 * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which
105 * operation. Right now we'll just have to live with this.
106 */
107void clearCommandBuffer()
108{
109 //This is a very simple operation
ad939de5 110 pthread_mutex_lock(&rxBufferMutex);
f5ecd97b 111 cmd_tail = cmd_head;
ad939de5 112 pthread_mutex_unlock(&rxBufferMutex);
f5ecd97b 113}
114
115/**
116 * @brief storeCommand stores a USB command in a circular buffer
117 * @param UC
118 */
ad939de5 119static void storeCommand(UsbCommand *command)
f5ecd97b 120{
ad939de5 121 pthread_mutex_lock(&rxBufferMutex);
f5ecd97b 122 if( (cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail)
123 {
124 // If these two are equal, we're about to overwrite in the
125 // circular buffer.
126 PrintAndLog("WARNING: Command buffer about to overwrite command! This needs to be fixed!");
127 }
128
129 // Store the command at the 'head' location
ad939de5 130 UsbCommand* destination = &rxBuffer[cmd_head];
f5ecd97b 131 memcpy(destination, command, sizeof(UsbCommand));
132
133 cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap
ad939de5 134 pthread_mutex_unlock(&rxBufferMutex);
f5ecd97b 135}
136
137
138/**
139 * @brief getCommand gets a command from an internal circular buffer.
140 * @param response location to write command
141 * @return 1 if response was returned, 0 if nothing has been received
142 */
ad939de5 143static int getCommand(UsbCommand* response)
f5ecd97b 144{
ad939de5 145 pthread_mutex_lock(&rxBufferMutex);
f5ecd97b 146 //If head == tail, there's nothing to read, or if we just got initialized
147 if (cmd_head == cmd_tail){
ad939de5 148 pthread_mutex_unlock(&rxBufferMutex);
f5ecd97b 149 return 0;
150 }
151
152 //Pick out the next unread command
ad939de5 153 UsbCommand* last_unread = &rxBuffer[cmd_tail];
f5ecd97b 154 memcpy(response, last_unread, sizeof(UsbCommand));
155 //Increment tail - this is a circular buffer, so modulo buffer size
156 cmd_tail = (cmd_tail + 1) % CMD_BUFFER_SIZE;
157
ad939de5 158 pthread_mutex_unlock(&rxBufferMutex);
f5ecd97b 159 return 1;
160}
161
162
babca445 163//----------------------------------------------------------------------------------
164// Entry point into our code: called whenever we received a packet over USB.
165// Handle debug commands directly, store all other commands in circular buffer.
166//----------------------------------------------------------------------------------
818efbeb 167static void UsbCommandReceived(UsbCommand *UC)
f5ecd97b 168{
169 switch(UC->cmd) {
170 // First check if we are handling a debug message
171 case CMD_DEBUG_PRINT_STRING: {
172 char s[USB_CMD_DATA_SIZE+1];
173 memset(s, 0x00, sizeof(s));
174 size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
175 memcpy(s,UC->d.asBytes,len);
176 PrintAndLog("#db# %s", s);
177 return;
178 } break;
179
180 case CMD_DEBUG_PRINT_INTEGERS: {
181 PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
182 return;
183 } break;
184
f5ecd97b 185 default:
929b61c6 186 storeCommand(UC);
f5ecd97b 187 break;
188 }
189
190}
191
192
b8ed9975 193static bool receive_from_serial(serial_port sp, uint8_t *rx_buf, size_t len, size_t *received_len) {
194 size_t bytes_read = 0;
195 *received_len = 0;
196 // we eventually need to call uart_receive several times if it times out in the middle of a transfer
197 while (uart_receive(sp, rx_buf + *received_len, len - *received_len, &bytes_read) && bytes_read && *received_len < len) {
929b61c6 198 #ifdef COMMS_DEBUG
b8ed9975 199 if (bytes_read != len - *received_len) {
200 printf("uart_receive() returned true but not enough bytes could be received. received: %d, wanted to receive: %d, already received before: %d\n",
201 bytes_read, len - *received_len, *received_len);
202 }
929b61c6 203 #endif
b8ed9975 204 *received_len += bytes_read;
205 bytes_read = 0;
206 }
207 return (*received_len == len);
208}
929b61c6 209
b8ed9975 210
ad939de5 211static void
f5ecd97b 212#ifdef __has_attribute
213#if __has_attribute(force_align_arg_pointer)
929b61c6 214__attribute__((force_align_arg_pointer))
f5ecd97b 215#endif
216#endif
ad939de5 217*uart_communication(void *targ) {
218 communication_arg_t *conn = (communication_arg_t*)targ;
b8ed9975 219 uint8_t rx[sizeof(UsbCommand)];
220 size_t rxlen = 0;
221 uint8_t *prx = rx;
222 UsbCommand *command = (UsbCommand*)rx;
223 UsbResponse *response = (UsbResponse*)rx;
f5ecd97b 224
2a537311
A
225#if defined(__MACH__) && defined(__APPLE__)
226 disableAppNap("Proxmark3 polling UART");
227#endif
228
818efbeb 229 while (conn->run) {
ad939de5 230 bool ACK_received = false;
b8ed9975 231 prx = rx;
232 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)
233 if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
f5ecd97b 234 prx += rxlen;
b8ed9975 235 if (response->cmd & CMD_VARIABLE_SIZE_FLAG) { // new style response with variable size
929b61c6 236 // PrintAndLog("received new style response %04" PRIx16 ", datalen = %d, arg[0] = %08" PRIx32 ", arg[1] = %08" PRIx32 ", arg[2] = %08" PRIx32 "\n",
b8ed9975 237 // response->cmd, response->datalen, response->arg[0], response->arg[1], response->arg[2]);
238 bytes_to_read = response->datalen;
239 if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
240 UsbCommand resp;
929b61c6 241 resp.cmd = response->cmd & ~CMD_VARIABLE_SIZE_FLAG; // remove the flag
b8ed9975 242 resp.arg[0] = response->arg[0];
243 resp.arg[1] = response->arg[1];
244 resp.arg[2] = response->arg[2];
245 memcpy(&resp.d.asBytes, &response->d.asBytes, response->datalen);
246 UsbCommandReceived(&resp);
247 if (resp.cmd == CMD_ACK) {
248 ACK_received = true;
249 }
250 }
251 } else { // old style response uses same data structure as commands. Fixed size.
929b61c6 252 // PrintAndLog("received old style response %016" PRIx64 ", arg[0] = %016" PRIx64 "\n", command->cmd, command->arg[0]);
b8ed9975 253 bytes_to_read = sizeof(UsbCommand) - bytes_to_read;
929b61c6 254 if (receive_from_serial(sp, prx, bytes_to_read, &rxlen)) {
b8ed9975 255 UsbCommandReceived(command);
256 if (command->cmd == CMD_ACK) {
257 ACK_received = true;
258 }
259 }
ad939de5 260 }
f5ecd97b 261 }
f5ecd97b 262
929b61c6 263 pthread_mutex_lock(&txBufferMutex);
264 // if we received an ACK the PM has done its job and waits for another command.
265 // We therefore can wait here as well until a new command is to be transmitted.
266 // The advantage is that the next command will be transmitted immediately without the need to wait for a receive timeout
267 if (ACK_received) {
268 while (!txBuffer_pending) {
269 pthread_cond_wait(&txBufferSig, &txBufferMutex);
ad939de5 270 }
271 }
929b61c6 272 if (txBuffer_pending) {
ad939de5 273 if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) {
f5ecd97b 274 PrintAndLog("Sending bytes to proxmark failed");
275 }
ad939de5 276 txBuffer_pending = false;
f5ecd97b 277 }
929b61c6 278 pthread_cond_signal(&txBufferSig); // tell main thread that txBuffer is empty
ad939de5 279 pthread_mutex_unlock(&txBufferMutex);
f5ecd97b 280 }
281
2a537311
A
282#if defined(__MACH__) && defined(__APPLE__)
283 enableAppNap();
284#endif
285
f5ecd97b 286 pthread_exit(NULL);
287 return NULL;
288}
289
290
babca445 291/**
292 * Data transfer from Proxmark to client. This method times out after
293 * ms_timeout milliseconds.
294 * @brief GetFromBigBuf
295 * @param dest Destination address for transfer
296 * @param bytes number of bytes to be transferred
297 * @param start_index offset into Proxmark3 BigBuf[]
298 * @param response struct to copy last command (CMD_ACK) into
299 * @param ms_timeout timeout in milliseconds
300 * @param show_warning display message after 2 seconds
301 * @return true if command was returned, otherwise false
302 */
303bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning)
304{
305 UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
306 SendCommand(&c);
307
308 uint64_t start_time = msclock();
309
310 UsbCommand resp;
929b61c6 311 if (response == NULL) {
babca445 312 response = &resp;
313 }
314
315 int bytes_completed = 0;
316 while(true) {
317 if (getCommand(response)) {
318 if (response->cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
319 int copy_bytes = MIN(bytes - bytes_completed, response->arg[1]);
320 memcpy(dest + response->arg[0], response->d.asBytes, copy_bytes);
321 bytes_completed += copy_bytes;
322 } else if (response->cmd == CMD_ACK) {
323 return true;
324 }
325 }
326
327 if (msclock() - start_time > ms_timeout) {
328 break;
329 }
330
331 if (msclock() - start_time > 2000 && show_warning) {
332 PrintAndLog("Waiting for a response from the proxmark...");
333 PrintAndLog("You can cancel this operation by pressing the pm3 button");
334 show_warning = false;
335 }
336 }
337
338 return false;
339}
340
929b61c6 341
fc52fbd4 342bool GetFromFpgaRAM(uint8_t *dest, int bytes)
343{
344 UsbCommand c = {CMD_HF_PLOT, {0, 0, 0}};
345 SendCommand(&c);
346
347 uint64_t start_time = msclock();
348
349 UsbCommand response;
929b61c6 350
fc52fbd4 351 int bytes_completed = 0;
352 bool show_warning = true;
353 while(true) {
354 if (getCommand(&response)) {
355 if (response.cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
356 int copy_bytes = MIN(bytes - bytes_completed, response.arg[1]);
357 memcpy(dest + response.arg[0], response.d.asBytes, copy_bytes);
358 bytes_completed += copy_bytes;
359 } else if (response.cmd == CMD_ACK) {
360 return true;
361 }
362 }
363
364 if (msclock() - start_time > 2000 && show_warning) {
365 PrintAndLog("Waiting for a response from the proxmark...");
366 PrintAndLog("You can cancel this operation by pressing the pm3 button");
367 show_warning = false;
368 }
369 }
370
371 return false;
372}
373
374
929b61c6 375bool OpenProxmark(void *port, bool wait_for_port, int timeout) {
ad939de5 376 char *portname = (char *)port;
377 if (!wait_for_port) {
378 sp = uart_open(portname);
379 } else {
380 printf("Waiting for Proxmark to appear on %s ", portname);
381 fflush(stdout);
382 int openCount = 0;
383 do {
384 sp = uart_open(portname);
385 msleep(1000);
386 printf(".");
387 fflush(stdout);
388 } while(++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT));
389 printf("\n");
390 }
391
392 // check result of uart opening
393 if (sp == INVALID_SERIAL_PORT) {
394 printf("ERROR: invalid serial port\n");
395 sp = NULL;
396 serial_port_name = NULL;
397 return false;
398 } else if (sp == CLAIMED_SERIAL_PORT) {
399 printf("ERROR: serial port is claimed by another process\n");
400 sp = NULL;
401 serial_port_name = NULL;
402 return false;
403 } else {
404 // start the USB communication thread
405 serial_port_name = portname;
406 conn.run = true;
ad939de5 407 pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn);
408 return true;
409 }
410}
411
412
413void CloseProxmark(void) {
414 conn.run = false;
7b2cd970
MF
415
416#ifdef __BIONIC__
417 // In Android O and later, if an invalid pthread_t is passed to pthread_join, it calls fatal().
418 // https://github.com/aosp-mirror/platform_bionic/blob/ed16b344e75f422fb36fbfd91fb30de339475880/libc/bionic/pthread_internal.cpp#L116-L128
419 //
420 // In Bionic libc, pthread_t is an integer.
421
422 if (USB_communication_thread != 0) {
423 pthread_join(USB_communication_thread, NULL);
424 }
425#else
426 // pthread_t is a struct on other libc, treat as an opaque memory reference
ad939de5 427 pthread_join(USB_communication_thread, NULL);
7b2cd970 428#endif
2bb7f7e3
MF
429
430 if (sp) {
431 uart_close(sp);
432 }
433
577b1c27 434#if defined(__linux__) && !defined(NO_UNLINK)
ad939de5 435 // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/*
577b1c27
MF
436 //
437 // This may be disabled at compile-time with -DNO_UNLINK (used for a JNI-based serial port on Android).
ad939de5 438 if (serial_port_name) {
439 unlink(serial_port_name);
440 }
441#endif
2bb7f7e3
MF
442
443 // Clean up our state
444 sp = NULL;
445 serial_port_name = NULL;
eed83b91 446#ifdef __BIONIC__
7b2cd970 447 memset(&USB_communication_thread, 0, sizeof(pthread_t));
eed83b91 448#endif
ad939de5 449}
450
babca445 451
f5ecd97b 452/**
453 * Waits for a certain response type. This method waits for a maximum of
454 * ms_timeout milliseconds for a specified response command.
455 *@brief WaitForResponseTimeout
61aaee35 456 * @param cmd command to wait for, or CMD_UNKNOWN to take any command.
f5ecd97b 457 * @param response struct to copy received command into.
458 * @param ms_timeout
babca445 459 * @param show_warning display message after 2 seconds
f5ecd97b 460 * @return true if command was returned, otherwise false
461 */
462bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) {
463
464 UsbCommand resp;
465
61aaee35 466 #ifdef COMMS_DEBUG
467 printf("Waiting for %04x cmd\n", cmd);
468 #endif
469
f5ecd97b 470 if (response == NULL) {
471 response = &resp;
472 }
473
474 uint64_t start_time = msclock();
475
476 // Wait until the command is received
477 while (true) {
929b61c6 478 while (getCommand(response)) {
61aaee35 479 if (cmd == CMD_UNKNOWN || response->cmd == cmd) {
f5ecd97b 480 return true;
481 }
482 }
483
484 if (msclock() - start_time > ms_timeout) {
485 break;
486 }
487
488 if (msclock() - start_time > 2000 && show_warning) {
61aaee35 489 // 2 seconds elapsed (but this doesn't mean the timeout was exceeded)
f5ecd97b 490 PrintAndLog("Waiting for a response from the proxmark...");
491 PrintAndLog("You can cancel this operation by pressing the pm3 button");
492 show_warning = false;
493 }
494 }
495 return false;
496}
497
498
499bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
500 return WaitForResponseTimeoutW(cmd, response, ms_timeout, true);
501}
502
503bool WaitForResponse(uint32_t cmd, UsbCommand* response) {
504 return WaitForResponseTimeoutW(cmd, response, -1, true);
505}
506
Impressum, Datenschutz