added a thread that starts when a device is detected to be offline. It runs until it finds a device and reconnects to it. Signals the READLINE hook event and the prompt is updated to match current status. This removes the need to type "hw connect" on clients that has been compiled with READLINE lib.

This commit is contained in:
iceman1001
2023-12-31 15:25:58 +01:00
parent e9996d081c
commit 20eddd8250
4 changed files with 120 additions and 2 deletions
+1
View File
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added a thread to check when device comes online again. It will connect and update prompt (@iceman1001)
- Changed CLI offline prompt - replaces the old prompt when offline is detected (@iceman100)
- Changed `hf mf info` - it now uses found keys to try identify Gen2 cards (@iceman1001)
- Changed `hf 14a info` - disabled debug logging while performing the magic tests (@iceman1001)
+97 -1
View File
@@ -29,6 +29,7 @@
#include "util.h" // g_pendingPrompt
#include "util_posix.h" // msclock
#include "util_darwin.h" // en/dis-ableNapp();
#include "usart_defs.h"
// #define COMMS_DEBUG
// #define COMMS_DEBUG_RAW
@@ -40,6 +41,10 @@ communication_arg_t g_conn;
capabilities_t g_pm3_capabilities;
static pthread_t communication_thread;
static pthread_t reconnect_thread;
static bool reconnect_ok = false;
static bool comm_thread_dead = false;
static bool comm_raw_mode = false;
static uint8_t *comm_raw_data = NULL;
@@ -334,6 +339,52 @@ static void PacketResponseReceived(PacketResponseNG *packet) {
}
}
// The reconnect device thread.
// When communication thread is dead, start up and try to start it again
void *uart_reconnect(void *targ) {
communication_arg_t *connection = (communication_arg_t *)targ;
#if defined(__MACH__) && defined(__APPLE__)
disableAppNap("Proxmark3 polling UART");
#endif
uint32_t speed = USART_BAUD_RATE;
if (connection->uart_speed) {
speed = connection->uart_speed;
}
while (1) {
if (OpenProxmarkSilent(&g_session.current_device, connection->serial_port_name, speed) == false) {
continue;
}
if (g_session.pm3_present && (TestProxmark(g_session.current_device) != PM3_SUCCESS)) {
CloseProxmark(g_session.current_device);
} else {
break;
}
}
#if defined(__MACH__) && defined(__APPLE__)
enableAppNap();
#endif
__atomic_test_and_set(&reconnect_ok, __ATOMIC_SEQ_CST);
pthread_exit(NULL);
return NULL;
}
void StartReconnectProxmark(void) {
pthread_create(&reconnect_thread, NULL, &uart_reconnect, &g_conn);
}
bool IsReconnectedOk(void) {
bool ret = __atomic_load_n(&reconnect_ok, __ATOMIC_SEQ_CST);
return ret;
}
// The communications thread.
// signals to main thread when a response is ready to process.
@@ -605,6 +656,8 @@ bool IsCommunicationThreadDead(void) {
return ret;
}
// To start raw receive mode:
// 1. Call SetCommunicationRawReceiveBuffer(...)
// 2. Call SetCommunicationReceiveMode(true)
@@ -644,6 +697,47 @@ size_t GetCommunicationRawReceiveNum(void) {
return __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST);
}
bool OpenProxmarkSilent(pm3_device_t **dev, const char *port, uint32_t speed) {
sp = uart_open(port, speed);
// check result of uart opening
if (sp == INVALID_SERIAL_PORT) {
sp = NULL;
return false;
} else if (sp == CLAIMED_SERIAL_PORT) {
sp = NULL;
return false;
} else {
// start the communication thread
if (port != g_conn.serial_port_name) {
uint16_t len = MIN(strlen(port), FILE_PATH_SIZE - 1);
memset(g_conn.serial_port_name, 0, FILE_PATH_SIZE);
memcpy(g_conn.serial_port_name, port, len);
}
g_conn.run = true;
g_conn.block_after_ACK = false;
// Flags to tell where to add CRC on sent replies
g_conn.send_with_crc_on_usb = false;
g_conn.send_with_crc_on_fpc = true;
// "Session" flag, to tell via which interface next msgs should be sent: USB or FPC USART
g_conn.send_via_fpc_usart = false;
pthread_create(&communication_thread, NULL, &uart_communication, &g_conn);
__atomic_clear(&comm_thread_dead, __ATOMIC_SEQ_CST);
__atomic_clear(&reconnect_ok, __ATOMIC_SEQ_CST);
g_session.pm3_present = true; // TODO support for multiple devices
fflush(stdout);
if (*dev == NULL) {
*dev = calloc(sizeof(pm3_device_t), sizeof(uint8_t));
}
(*dev)->g_conn = &g_conn; // TODO g_conn shouldn't be global
return true;
}
}
bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) {
if (!wait_for_port) {
@@ -817,8 +911,10 @@ void CloseProxmark(pm3_device_t *dev) {
// ~ = 12000000 / USART_BAUD_RATE
// Let's take 2x (maybe we need more for BT link?)
static size_t communication_delay(void) {
if (g_conn.send_via_fpc_usart) // needed also for Windows USB USART??
// needed also for Windows USB USART??
if (g_conn.send_via_fpc_usart) {
return 2 * (12000000 / g_conn.uart_speed);
}
return 0;
}
+8
View File
@@ -89,6 +89,9 @@ typedef struct pm3_device {
int script_embedded;
} pm3_device_t;
void *uart_reconnect(void *targ);
void *uart_receiver(void *targ);
void SendCommandBL(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
@@ -97,13 +100,18 @@ void SendCommandMIX(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, v
void clearCommandBuffer(void);
#define FLASHMODE_SPEED 460800
bool IsReconnectedOk(void);
bool IsCommunicationThreadDead(void);
bool SetCommunicationReceiveMode(bool isRawMode);
void SetCommunicationRawReceiveBuffer(uint8_t *buffer, size_t len);
size_t GetCommunicationRawReceiveNum(void);
bool OpenProxmarkSilent(pm3_device_t **dev, const char *port, uint32_t speed);
bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed);
int TestProxmark(pm3_device_t *dev);
void CloseProxmark(pm3_device_t *dev);
void StartReconnectProxmark(void);
size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process);
bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout, bool show_warning);
+14 -1
View File
@@ -133,10 +133,12 @@ static void prompt_compose(char *buf, size_t buflen, const char *promptctx, cons
if (no_newline) {
snprintf(buf, buflen - 1, PROXPROMPT_COMPOSE, promptdev, promptnet, promptctx);
} else {
snprintf(buf, buflen - 1, "\r" PROXPROMPT_COMPOSE, promptdev, promptnet, promptctx);
snprintf(buf, buflen - 1, "\r \r" PROXPROMPT_COMPOSE, promptdev, promptnet, promptctx);
}
}
// This function is hooked via RL_EVENT_HOOK.
static int check_comm(void) {
// If communications thread goes down. Device disconnected then this should hook up PM3 again.
if (IsCommunicationThreadDead() && g_session.pm3_present) {
@@ -148,7 +150,18 @@ static int check_comm(void) {
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !g_session.supports_colors);
pm3line_update_prompt(prompt_filtered);
CloseProxmark(g_session.current_device);
StartReconnectProxmark();
}
// its alive again
if (IsReconnectedOk() && g_session.pm3_present) {
prompt_dev = PROXPROMPT_DEV_USB;
char prompt[PROXPROMPT_MAX_SIZE] = {0};
prompt_compose(prompt, sizeof(prompt), prompt_ctx, prompt_dev, prompt_net, false);
char prompt_filtered[PROXPROMPT_MAX_SIZE] = {0};
memcpy_filter_ansi(prompt_filtered, prompt, sizeof(prompt_filtered), !g_session.supports_colors);
pm3line_update_prompt(prompt_filtered);
}
msleep(10);
return 0;
}