Add 'hf.field.timeout' to prefs

This commit is contained in:
kormax
2026-03-31 12:02:23 +03:00
parent bdb05a8037
commit b443fc7723
9 changed files with 172 additions and 1 deletions
+29 -1
View File
@@ -91,10 +91,13 @@
int g_dbglevel = DBG_ERROR;
uint8_t g_trigger = 0;
bool g_hf_field_active = false;
bool g_hf_field_timeout_active = false;
extern uint32_t _stack_start[], _stack_end[];
common_area_t g_common_area __attribute__((section(".commonarea")));
static int button_status = BUTTON_NO_CLICK;
static bool allow_send_wtx = false;
static uint32_t g_hf_field_activity_timeout_ms = 0;
static uint32_t g_last_activity_ms = 0;
uint16_t g_tearoff_delay_us = 0;
bool g_tearoff_enabled = false;
uint8_t g_tearoff_skip = 0;
@@ -125,6 +128,7 @@ void hf_field_off(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
g_hf_field_active = false;
g_hf_field_timeout_active = false;
}
void send_wtx(uint16_t wtx) {
@@ -1002,6 +1006,18 @@ static void PacketReceived(PacketCommandNG *packet) {
reply_ng(CMD_SET_TEAROFF, PM3_SUCCESS, NULL, 0);
break;
}
case CMD_SET_HF_FIELD_TIMEOUT: {
if (packet->length != sizeof(uint32_t)) {
reply_ng(CMD_SET_HF_FIELD_TIMEOUT, PM3_EINVARG, NULL, 0);
break;
}
uint32_t timeout_ms = 0;
memcpy(&timeout_ms, packet->data.asBytes, sizeof(timeout_ms));
g_hf_field_activity_timeout_ms = timeout_ms;
g_last_activity_ms = GetTickCount();
reply_ng(CMD_SET_HF_FIELD_TIMEOUT, PM3_SUCCESS, NULL, 0);
break;
}
// always available
case CMD_HF_DROPFIELD: {
hf_field_off();
@@ -2699,6 +2715,8 @@ static void PacketReceived(PacketCommandNG *packet) {
}
case CMD_FPGA_MAJOR_MODE_OFF: { // ## FPGA Control
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
g_hf_field_active = false;
g_hf_field_timeout_active = false;
SpinDelay(200);
LED_D_OFF(); // LED D indicates field ON or OFF
break;
@@ -3315,6 +3333,7 @@ void __attribute__((noreturn)) AppMain(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
StartTickCount();
g_last_activity_ms = GetTickCount();
#ifdef WITH_LCD
LCDInit();
@@ -3378,12 +3397,21 @@ void __attribute__((noreturn)) AppMain(void) {
int ret = receive_ng(&rx);
if (ret == PM3_SUCCESS) {
PacketReceived(&rx);
g_last_activity_ms = GetTickCount();
} else if (ret != PM3_ENODATA) {
Dbprintf("Error in frame reception: %d %s", ret, (ret == PM3_EIO) ? "PM3_EIO" : "");
// TODO if error, shall we resync ?
}
if (g_hf_field_activity_timeout_ms > 0 && g_hf_field_timeout_active) {
if (GetTickCountDelta(g_last_activity_ms) >= g_hf_field_activity_timeout_ms) {
if (g_dbglevel >= DBG_INFO) {
Dbprintf("HF field auto-off: inactivity timeout (%u ms)", g_hf_field_activity_timeout_ms);
}
hf_field_off();
}
}
// Press button for one second to enter a possible standalone mode
button_status = BUTTON_HELD(1000);
if (button_status == BUTTON_HOLD) {
+1
View File
@@ -24,6 +24,7 @@
extern uint8_t g_trigger;
extern bool g_hf_field_active;
extern bool g_hf_field_timeout_active;
void hf_field_off(void);
int tearoff_hook(void);
+26
View File
@@ -562,12 +562,38 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) {
AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data
while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete
}
//-----------------------------------------------------------------------------
// Write the FPGA setup word (that determines what mode the logic is in, read
// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
// avoid changing this function's occurrence everywhere in the source code.
//-----------------------------------------------------------------------------
void FpgaWriteConfWord(uint16_t v) {
const int current = FpgaGetCurrent();
// Keep track of whether or not we should be monitoring the HF field timeout
if (current == FPGA_BITSTREAM_HF || current == FPGA_BITSTREAM_HF_15 || current == FPGA_BITSTREAM_HF_FELICA) {
const uint16_t major = v & FPGA_MAJOR_MODE_MASK;
const uint16_t minor = v & FPGA_MINOR_MODE_MASK;
switch (major) {
case FPGA_MAJOR_MODE_HF_READER:
g_hf_field_timeout_active = true;
break;
case FPGA_MAJOR_MODE_HF_ISO14443A:
g_hf_field_timeout_active = (minor == FPGA_HF_ISO14443A_READER_LISTEN || minor == FPGA_HF_ISO14443A_READER_MOD);
break;
case FPGA_MAJOR_MODE_HF_ISO18092:
g_hf_field_timeout_active = (minor & FPGA_HF_ISO18092_FLAG_READER) != 0;
break;
default:
g_hf_field_timeout_active = false;
break;
}
} else {
g_hf_field_timeout_active = false;
}
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
}
+29
View File
@@ -846,6 +846,28 @@ bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int
}
}
int SetHfFieldTimeout(uint32_t timeout_ms, bool quiet) {
if (g_session.pm3_present == false) {
return PM3_ENOTTY;
}
clearCommandBuffer();
SendCommandNG(CMD_SET_HF_FIELD_TIMEOUT, (uint8_t *)&timeout_ms, sizeof(timeout_ms));
PacketResponseNG resp;
if (WaitForResponseTimeoutW(CMD_SET_HF_FIELD_TIMEOUT, &resp, 1000, false) == false) {
if (!quiet) {
PrintAndLogEx(WARNING, "timeout while setting HF field timeout");
}
return PM3_ETIMEOUT;
}
if (resp.status != PM3_SUCCESS && !quiet) {
PrintAndLogEx(WARNING, "HF field timeout command failed (%d)", resp.status);
}
return resp.status;
}
// check if we can communicate with Pm3
int TestProxmark(pm3_device_t *dev) {
@@ -921,6 +943,13 @@ int TestProxmark(pm3_device_t *dev) {
return res;
}
}
if (g_session.hf_field_timeout > 0) {
int timeout_res = SetHfFieldTimeout(g_session.hf_field_timeout, true);
if (timeout_res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Failed to apply HF field timeout (" _YELLOW_("%u") " ms)", g_session.hf_field_timeout);
}
}
return PM3_SUCCESS;
}
+2
View File
@@ -120,6 +120,8 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms
bool WaitForResponseTimeout(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout);
bool WaitForResponse(uint32_t cmd, PacketResponseNG *response);
int SetHfFieldTimeout(uint32_t timeout_ms, bool quiet);
//bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, PacketResponseNG *response, size_t ms_timeout, bool show_warning);
bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, uint8_t *data, uint32_t datalen, PacketResponseNG *response, size_t ms_timeout, bool show_warning);
+2
View File
@@ -45,6 +45,7 @@ const static vocabulary_t vocabulary[] = {
{ 1, "prefs get client.debug" },
{ 1, "prefs get client.delay" },
{ 1, "prefs get client.timeout" },
{ 1, "prefs get hf.field.timeout" },
{ 1, "prefs get color" },
{ 1, "prefs get savepaths" },
{ 1, "prefs get emoji" },
@@ -57,6 +58,7 @@ const static vocabulary_t vocabulary[] = {
{ 1, "prefs set client.debug" },
{ 1, "prefs set client.delay" },
{ 1, "prefs set client.timeout" },
{ 1, "prefs set hf.field.timeout" },
{ 1, "prefs set color" },
{ 1, "prefs set emoji" },
{ 1, "prefs set hints" },
+81
View File
@@ -102,6 +102,7 @@ int preferences_load(void) {
g_session.client_debug_level = cdbOFF;
// g_session.device_debug_level = ddbOFF;
g_session.timeout = uart_get_timeouts();
g_session.hf_field_timeout = 0;
g_session.window_changed = false;
g_session.plot.x = 10;
@@ -329,6 +330,7 @@ void preferences_save_callback(json_t *root) {
*/
JsonSaveInt(root, "client.exe.delay", g_session.client_exe_delay);
JsonSaveInt(root, "client.timeout", g_session.timeout);
JsonSaveInt(root, "hf.field.timeout", g_session.hf_field_timeout);
// MQTT
JsonSaveStr(root, "mqtt.server", g_session.mqtt_server);
@@ -440,6 +442,14 @@ void preferences_load_callback(json_t *root) {
if (json_unpack_ex(root, &up_error, 0, "{s:i}", "client.timeout", &i1) == 0)
g_session.timeout = i1;
// persistent HF field timeout
if (json_unpack_ex(root, &up_error, 0, "{s:i}", "hf.field.timeout", &i1) == 0) {
g_session.hf_field_timeout = i1;
} else if (json_unpack_ex(root, &up_error, 0, "{s:i}", "field.timeout", &i1) == 0) {
// Backward compatibility with earlier key name.
g_session.hf_field_timeout = i1;
}
// MQTT server
if (json_unpack_ex(root, &up_error, 0, "{s:s}", "mqtt.server", &s1) == 0)
setDefaultMqttServer(s1);
@@ -671,6 +681,14 @@ static void showClientTimeoutState(void) {
PrintAndLogEx(INFO, " communication timeout... " _GREEN_("%u") " ms", g_session.timeout);
}
static void showFieldTimeoutState(void) {
if (g_session.hf_field_timeout == 0) {
PrintAndLogEx(INFO, " HF field timeout........ " _WHITE_("off"));
} else {
PrintAndLogEx(INFO, " HF field timeout........ " _GREEN_("%u") " ms", g_session.hf_field_timeout);
}
}
static void showMqttServer(prefShowOpt_t opt) {
if ((g_session.mqtt_server == NULL) || (strcmp(g_session.mqtt_server, "") == 0)) {
PrintAndLogEx(INFO, " MQTT server.............%s "_WHITE_("not set"), pref_show_status_msg(opt));
@@ -1067,6 +1085,50 @@ static int setCmdClientTimeout(const char *Cmd) {
return PM3_SUCCESS;
}
static int setCmdHfFieldTimeout(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "prefs set hf.field.timeout",
"Set persistent preference of PM3 HF field inactivity timeout",
"prefs set hf.field.timeout --ms 0 --> disable HF field auto timeout\n"
"prefs set hf.field.timeout --ms 5000 --> turn HF field off after 5s of inactivity\n"
"prefs set hf.field.timeout --ms 300000 --> turn HF field off after 5 minutes of inactivity\n"
"prefs set hf.field.timeout --ms 900000 --> turn HF field off after 15 minutes of inactivity\n");
void *argtable[] = {
arg_param_begin,
arg_int0("m", "ms", "<ms>", "HF field inactivity timeout in milliseconds"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int32_t arg = arg_get_int_def(ctx, 1, -1);
CLIParserFree(ctx);
if (arg < 0) {
showFieldTimeoutState();
return PM3_SUCCESS;
}
uint32_t new_value = (uint32_t)arg;
if (g_session.hf_field_timeout != new_value) {
showFieldTimeoutState();
g_session.hf_field_timeout = new_value;
showFieldTimeoutState();
preferences_save();
} else {
showFieldTimeoutState();
}
if (g_session.pm3_present) {
int res = SetHfFieldTimeout(g_session.hf_field_timeout, false);
if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Failed to apply HF field timeout to connected PM3");
}
}
return PM3_SUCCESS;
}
static int setCmdHint(const char *Cmd) {
CLIParserContext *ctx;
@@ -1517,6 +1579,22 @@ static int getCmdClientTimeout(const char *Cmd) {
return PM3_SUCCESS;
}
static int getCmdHfFieldTimeout(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "prefs get hf.field.timeout",
"Get preference of PM3 HF field inactivity timeout",
"prefs get hf.field.timeout"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
showFieldTimeoutState();
return PM3_SUCCESS;
}
static int getCmdMqtt(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "prefs get mqtt",
@@ -1540,6 +1618,7 @@ static command_t CommandTableGet[] = {
{"client.debug", getCmdDebug, AlwaysAvailable, "Get client debug level preference"},
{"client.delay", getCmdExeDelay, AlwaysAvailable, "Get client execution delay preference"},
{"client.timeout", getCmdClientTimeout, AlwaysAvailable, "Get client execution delay preference"},
{"hf.field.timeout", getCmdHfFieldTimeout, AlwaysAvailable, "Get PM3 HF field inactivity timeout preference"},
{"color", getCmdColor, AlwaysAvailable, "Get color support preference"},
{"savepaths", getCmdSavePaths, AlwaysAvailable, "Get file folder "},
// {"devicedebug", getCmdDeviceDebug, AlwaysAvailable, "Get device debug level"},
@@ -1557,6 +1636,7 @@ static command_t CommandTableSet[] = {
{"client.debug", setCmdDebug, AlwaysAvailable, "Set client debug level"},
{"client.delay", setCmdExeDelay, AlwaysAvailable, "Set client execution delay"},
{"client.timeout", setCmdClientTimeout, AlwaysAvailable, "Set client communication timeout"},
{"hf.field.timeout", setCmdHfFieldTimeout, AlwaysAvailable, "Set PM3 HF field inactivity timeout"},
{"color", setCmdColor, AlwaysAvailable, "Set color support"},
{"emoji", setCmdEmoji, AlwaysAvailable, "Set emoji display"},
@@ -1630,6 +1710,7 @@ static int CmdPrefShow(const char *Cmd) {
showClientExeDelayState();
showOutputState(prefShowNone);
showClientTimeoutState();
showFieldTimeoutState();
showMqttServer(prefShowNone);
showMqttPort(prefShowNone);
showMqttTopic(prefShowNone);
+1
View File
@@ -63,6 +63,7 @@ typedef struct {
char *history_path;
pm3_device_t *current_device;
uint32_t timeout;
uint32_t hf_field_timeout;
char *mqtt_server;
char *mqtt_port;
char *mqtt_topic;
+1
View File
@@ -531,6 +531,7 @@ typedef struct {
#define CMD_TIA 0x0117
#define CMD_BREAK_LOOP 0x0118
#define CMD_SET_TEAROFF 0x0119
#define CMD_SET_HF_FIELD_TIMEOUT 0x011A
#define CMD_GET_DBGMODE 0x0120
// RDV40, Flash memory operations