lf pcf7931 - now uses cliparser

This commit is contained in:
iceman1001 2020-12-01 21:52:08 +01:00
commit 84ebe37725

View file

@ -9,13 +9,12 @@
// Low frequency PCF7931 commands
//-----------------------------------------------------------------------------
#include "cmdlfpcf7931.h"
#include <string.h>
#include <ctype.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "ui.h"
#include "cliparser.h"
static int CmdHelp(const char *Cmd);
@ -37,87 +36,106 @@ int pcf7931_resetConfig(void) {
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
PrintAndLogEx(INFO, "Configuration resetted");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 config`") " to view current settings");
return PM3_SUCCESS;
}
int pcf7931_printConfig(void) {
PrintAndLogEx(NORMAL, "Password (LSB first on bytes) : %s", sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay);
PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth);
PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition);
PrintAndLogEx(INFO, "Password (LSB first on bytes)... " _YELLOW_("%s"), sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
PrintAndLogEx(INFO, "Tag initialization delay........ " _YELLOW_("%d") " us", configPcf.InitDelay);
PrintAndLogEx(INFO, "Offset low pulses width......... " _YELLOW_("%d") " us", configPcf.OffsetWidth);
PrintAndLogEx(INFO, "Offset low pulses position...... " _YELLOW_("%d") " us", configPcf.OffsetPosition);
return PM3_SUCCESS;
}
static int usage_pcf7931_read(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 read [h] ");
PrintAndLogEx(NORMAL, "This command tries to read a PCF7931 tag.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 read");
return PM3_SUCCESS;
}
static int CmdLFPCF7931Reader(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 reader",
"read a PCF7931 tag",
"lf pcf7931 reader -@ -> continuous reader mode"
);
static int usage_pcf7931_write(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 write [h] <block address> <byte address> <data>");
PrintAndLogEx(NORMAL, "This command tries to write a PCF7931 tag.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " blockaddress Block to save [0-7]");
PrintAndLogEx(NORMAL, " byteaddress Index of byte inside block to write [0-15]");
PrintAndLogEx(NORMAL, " data one byte of data (hex)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF");
return PM3_SUCCESS;
}
void *argtable[] = {
arg_param_begin,
arg_lit0("@", NULL, "optional - continuous reader mode"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool cm = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
static int usage_pcf7931_config(void) {
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>");
PrintAndLogEx(NORMAL, "This command tries to set the configuration used with PCF7931 commands");
PrintAndLogEx(NORMAL, "The time offsets could be useful to correct slew rate generated by the antenna");
PrintAndLogEx(NORMAL, "Caling without some parameter will print the current configuration.");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " r Reset configuration to default values");
PrintAndLogEx(NORMAL, " pwd Password, hex, 7bytes, LSB-order");
PrintAndLogEx(NORMAL, " delay Tag initialization delay (in us) decimal");
PrintAndLogEx(NORMAL, " offset Low pulses width (in us) decimal");
PrintAndLogEx(NORMAL, " offset Low pulses position (in us) decimal");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 config");
PrintAndLogEx(NORMAL, " lf pcf7931 config r");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30");
return PM3_SUCCESS;
}
static int CmdLFPCF7931Read(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_pcf7931_read();
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
if (cm) {
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
}
do {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
} while (cm && !kbd_enter_pressed());
return PM3_SUCCESS;
}
static int CmdLFPCF7931Config(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 config",
"This command tries to set the configuration used with PCF7931 commands\n"
"The time offsets could be useful to correct slew rate generated by the antenna\n"
"Caling without some parameter will print the current configuration.",
"lf pcf7931 config --reset\n"
"lf pcf7931 config --pwd 11223344556677 -d 20000\n"
"lf pcf7931 config --pwd 11223344556677 -d 17500 --lw -10 --lp 30"
);
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 0) return pcf7931_printConfig();
if (ctmp == 'h') return usage_pcf7931_config();
if (ctmp == 'r') return pcf7931_resetConfig();
void *argtable[] = {
arg_param_begin,
arg_lit0("r", "reset", "Reset configuration to default values"),
arg_str0("p", "pwd", "<hex>", "Password, 7bytes, LSB-order"),
arg_u64_0("d", "delay", "<dec>", "Tag initialization delay (in us)"),
arg_int0(NULL, "lw", "<dec>", "offset, low pulses width (in us)"),
arg_int0(NULL, "lp", "<dec>", "offset, low pulses position (in us)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config();
bool use_reset = arg_get_lit(ctx, 1);
if (use_reset) {
CLIParserFree(ctx);
return pcf7931_resetConfig();
}
configPcf.InitDelay = (param_get32ex(Cmd, 1, 0, 10) & 0xFFFF);
configPcf.OffsetWidth = (int)(param_get32ex(Cmd, 2, 0, 10) & 0xFFFF);
configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF);
int pwd_len = 0;
uint8_t pwd[7] = {0};
CLIGetHexWithReturn(ctx, 2, pwd, &pwd_len);
uint32_t delay = arg_get_u32_def(ctx, 3, -1);
int ow = arg_get_int_def(ctx, 4, 0xFFFF);
int op = arg_get_int_def(ctx, 5, 0xFFFF);
CLIParserFree(ctx);
if (pwd_len && pwd_len < sizeof(pwd)) {
PrintAndLogEx(ERR, "Password must be 7 bytes");
return PM3_EINVARG;
}
if (pwd_len) {
memcpy(configPcf.Pwd, pwd, sizeof(configPcf.Pwd));
}
if (delay != -1) {
configPcf.InitDelay = (delay & 0xFFFF);
}
if (ow != 0xFFFF) {
configPcf.OffsetWidth = (ow & 0xFFFF);
}
if (op != 0xFFFF) {
configPcf.OffsetPosition =(op & 0xFFFF);
}
pcf7931_printConfig();
return PM3_SUCCESS;
@ -125,21 +143,39 @@ static int CmdLFPCF7931Config(const char *Cmd) {
static int CmdLFPCF7931Write(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_pcf7931_write();
CLIParserContext *ctx;
CLIParserInit(&ctx, "lf pcf7931 write",
"This command tries to write a PCF7931 tag.",
"lf pcf7931 write --blk 2 --idx 1 -d FF -> Write 0xFF to block 2, index 1 "
);
uint8_t block = 0, bytepos = 0, data = 0;
void *argtable[] = {
arg_param_begin,
arg_u64_1("b", "blk", "<dec>", "[0-7] block number"),
arg_u64_1("i", "idx", "<dec>", "[0-15] index of byte inside block"),
arg_str1("d", "data", "<hex>", "one byte to be written"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t block = arg_get_u32_def(ctx, 1, 0);
uint8_t idx = arg_get_u32_def(ctx, 2, 0);
if (param_getdec(Cmd, 0, &block)) return usage_pcf7931_write();
if (param_getdec(Cmd, 1, &bytepos)) return usage_pcf7931_write();
int data_len = 0;
uint8_t data[1] = {0};
CLIGetHexWithReturn(ctx, 3, data, &data_len);
CLIParserFree(ctx);
if ((block > 7) || (bytepos > 15)) return usage_pcf7931_write();
if (block > 7) {
PrintAndLogEx(ERR, "out-of-range error, block must be between 0-7");
return PM3_EINVARG;
}
data = param_get8ex(Cmd, 2, 0, 16);
if (idx > 15) {
PrintAndLogEx(ERR, "out-of-range error, index must be between 0-15");
return PM3_EINVARG;
}
PrintAndLogEx(INFO, "Writing block: %d", block);
PrintAndLogEx(INFO, " pos: %d", bytepos);
PrintAndLogEx(INFO, " data: 0x%02X", data);
PrintAndLogEx(INFO, "Writing block %u at idx %u with data 0x%02X", block, idx, data[0]);
uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd));
@ -148,16 +184,16 @@ static int CmdLFPCF7931Write(const char *Cmd) {
buf[9] = configPcf.InitDelay;
clearCommandBuffer();
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf));
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, idx, data[0], buf, sizeof(buf));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 read`") " to verify");
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify");
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"read", CmdLFPCF7931Read, IfPm3Lf, "Read content of a PCF7931 transponder"},
{"reader", CmdLFPCF7931Reader, IfPm3Lf, "Read content of a PCF7931 transponder"},
{"write", CmdLFPCF7931Write, IfPm3Lf, "Write data on a PCF7931 transponder."},
{"config", CmdLFPCF7931Config, AlwaysAvailable, "Configure the password, the tags initialization delay and time offsets (optional)"},
{NULL, NULL, NULL, NULL}