mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-05 20:51:18 -07:00
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
This commit is contained in:
parent
3bcc4d77e1
commit
f5ecd97b15
16 changed files with 384 additions and 307 deletions
|
@ -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)), )
|
||||
|
|
152
client/cmdmain.c
152
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -15,13 +15,10 @@
|
|||
#include <stddef.h>
|
||||
#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
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
// Command parser
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "cmdparser.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ui.h"
|
||||
#include "cmdparser.h"
|
||||
#include "proxmark3.h"
|
||||
#include "comms.h"
|
||||
|
||||
|
||||
void CmdsHelp(const command_t Commands[])
|
||||
|
|
252
client/comms.c
Normal file
252
client/comms.c
Normal file
|
@ -0,0 +1,252 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// 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 <pthread.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
45
client/comms.h
Normal file
45
client/comms.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// 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 <stdbool.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#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_
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
# include <unistd.h>
|
||||
#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 <port> [-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 <DEVICE>',\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];
|
||||
|
||||
res = flash_start_flashing(can_write_bl,serial_port_name);
|
||||
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);
|
||||
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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <port> [-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);
|
||||
}
|
||||
|
|
|
@ -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, ...)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
14
uart/uart.h
14
uart/uart.h
|
@ -39,7 +39,15 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue