fix one too small
[RRG-proxmark3.git] / client / src / cmdlfpcf7931.c
blob067fecde209499c41900b22a561346ee8352bd43
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Low frequency PCF7931 commands
17 //-----------------------------------------------------------------------------
18 #include "cmdlfpcf7931.h"
19 #include <string.h>
20 #include <ctype.h>
21 #include "cmdparser.h" // command_t
22 #include "comms.h"
23 #include "ui.h"
24 #include "cliparser.h"
26 static int CmdHelp(const char *Cmd);
28 #define PCF7931_DEFAULT_INITDELAY 17500
29 #define PCF7931_DEFAULT_OFFSET_WIDTH 0
30 #define PCF7931_DEFAULT_OFFSET_POSITION 0
32 // Default values - Configuration
33 static struct pcf7931_config configPcf = {
34 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
35 PCF7931_DEFAULT_INITDELAY,
36 PCF7931_DEFAULT_OFFSET_WIDTH,
37 PCF7931_DEFAULT_OFFSET_POSITION
40 // Resets the configuration settings to default values.
41 int pcf7931_resetConfig(void) {
42 memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd));
43 configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
44 configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
45 configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
46 PrintAndLogEx(INFO, "Configuration reset");
47 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 config`") " to view current settings");
48 return PM3_SUCCESS;
51 int pcf7931_printConfig(void) {
52 PrintAndLogEx(INFO, "Password (LSB first on bytes)... " _YELLOW_("%s"), sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
53 PrintAndLogEx(INFO, "Tag initialization delay........ " _YELLOW_("%d") " us", configPcf.InitDelay);
54 PrintAndLogEx(INFO, "Offset low pulses width......... " _YELLOW_("%d") " us", configPcf.OffsetWidth);
55 PrintAndLogEx(INFO, "Offset low pulses position...... " _YELLOW_("%d") " us", configPcf.OffsetPosition);
56 return PM3_SUCCESS;
59 static int CmdLFPCF7931Reader(const char *Cmd) {
60 CLIParserContext *ctx;
61 CLIParserInit(&ctx, "lf pcf7931 reader",
62 "read a PCF7931 tag",
63 "lf pcf7931 reader -@ -> continuous reader mode"
66 void *argtable[] = {
67 arg_param_begin,
68 arg_lit0("@", NULL, "optional - continuous reader mode"),
69 arg_param_end
71 CLIExecWithReturn(ctx, Cmd, argtable, true);
72 bool cm = arg_get_lit(ctx, 1);
73 CLIParserFree(ctx);
75 if (cm) {
76 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
79 do {
80 PacketResponseNG resp;
81 clearCommandBuffer();
82 SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
83 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
84 PrintAndLogEx(WARNING, "command execution time out");
85 return PM3_ETIMEOUT;
87 } while (cm && !kbd_enter_pressed());
89 return PM3_SUCCESS;
92 static int CmdLFPCF7931Config(const char *Cmd) {
93 CLIParserContext *ctx;
94 CLIParserInit(&ctx, "lf pcf7931 config",
95 "This command tries to set the configuration used with PCF7931 commands\n"
96 "The time offsets could be useful to correct slew rate generated by the antenna\n"
97 "Caling without some parameter will print the current configuration.",
98 "lf pcf7931 config --reset\n"
99 "lf pcf7931 config --pwd 11223344556677 -d 20000\n"
100 "lf pcf7931 config --pwd 11223344556677 -d 17500 --lw -10 --lp 30"
103 void *argtable[] = {
104 arg_param_begin,
105 arg_lit0("r", "reset", "Reset configuration to default values"),
106 arg_str0("p", "pwd", "<hex>", "Password, 7bytes, LSB-order"),
107 arg_u64_0("d", "delay", "<dec>", "Tag initialization delay (in us)"),
108 arg_int0(NULL, "lw", "<dec>", "offset, low pulses width (in us)"),
109 arg_int0(NULL, "lp", "<dec>", "offset, low pulses position (in us)"),
110 arg_param_end
112 CLIExecWithReturn(ctx, Cmd, argtable, true);
114 bool use_reset = arg_get_lit(ctx, 1);
115 if (use_reset) {
116 CLIParserFree(ctx);
117 return pcf7931_resetConfig();
120 int pwd_len = 0;
121 uint8_t pwd[7] = {0};
122 CLIGetHexWithReturn(ctx, 2, pwd, &pwd_len);
124 uint32_t delay = arg_get_u32_def(ctx, 3, -1);
125 int ow = arg_get_int_def(ctx, 4, 0xFFFF);
126 int op = arg_get_int_def(ctx, 5, 0xFFFF);
127 CLIParserFree(ctx);
129 if (pwd_len && pwd_len < sizeof(pwd)) {
130 PrintAndLogEx(ERR, "Password must be 7 bytes");
131 return PM3_EINVARG;
134 if (pwd_len) {
135 memcpy(configPcf.Pwd, pwd, sizeof(configPcf.Pwd));
137 if (delay != -1) {
138 configPcf.InitDelay = (delay & 0xFFFF);
140 if (ow != 0xFFFF) {
141 configPcf.OffsetWidth = (ow & 0xFFFF);
143 if (op != 0xFFFF) {
144 configPcf.OffsetPosition = (op & 0xFFFF);
147 pcf7931_printConfig();
148 return PM3_SUCCESS;
151 static int CmdLFPCF7931Write(const char *Cmd) {
153 CLIParserContext *ctx;
154 CLIParserInit(&ctx, "lf pcf7931 write",
155 "This command tries to write a PCF7931 tag.",
156 "lf pcf7931 write --blk 2 --idx 1 -d FF -> Write 0xFF to block 2, index 1 "
159 void *argtable[] = {
160 arg_param_begin,
161 arg_u64_1("b", "blk", "<dec>", "[0-7] block number"),
162 arg_u64_1("i", "idx", "<dec>", "[0-15] index of byte inside block"),
163 arg_str1("d", "data", "<hex>", "one byte to be written"),
164 arg_param_end
166 CLIExecWithReturn(ctx, Cmd, argtable, true);
167 uint8_t block = arg_get_u32_def(ctx, 1, 0);
168 uint8_t idx = arg_get_u32_def(ctx, 2, 0);
170 int data_len = 0;
171 uint8_t data[1] = {0};
172 CLIGetHexWithReturn(ctx, 3, data, &data_len);
173 CLIParserFree(ctx);
175 if (block > 7) {
176 PrintAndLogEx(ERR, "out-of-range error, block must be between 0-7");
177 return PM3_EINVARG;
180 if (idx > 15) {
181 PrintAndLogEx(ERR, "out-of-range error, index must be between 0-15");
182 return PM3_EINVARG;
185 PrintAndLogEx(INFO, "Writing block %u at idx %u with data 0x%02X", block, idx, data[0]);
187 uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
188 memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd));
189 buf[7] = (configPcf.OffsetWidth + 128);
190 buf[8] = (configPcf.OffsetPosition + 128);
191 buf[9] = configPcf.InitDelay;
193 clearCommandBuffer();
194 SendCommandMIX(CMD_LF_PCF7931_WRITE, block, idx, data[0], buf, sizeof(buf));
196 PrintAndLogEx(SUCCESS, "Done");
197 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify");
198 return PM3_SUCCESS;
201 static command_t CommandTable[] = {
202 {"help", CmdHelp, AlwaysAvailable, "This help"},
203 {"reader", CmdLFPCF7931Reader, IfPm3Lf, "Read content of a PCF7931 transponder"},
204 {"write", CmdLFPCF7931Write, IfPm3Lf, "Write data on a PCF7931 transponder."},
205 {"config", CmdLFPCF7931Config, AlwaysAvailable, "Configure the password, the tags initialization delay and time offsets (optional)"},
206 {NULL, NULL, NULL, NULL}
209 static int CmdHelp(const char *Cmd) {
210 (void)Cmd; // Cmd is not used so far
211 CmdsHelp(CommandTable);
212 return PM3_SUCCESS;
215 int CmdLFPCF7931(const char *Cmd) {
216 clearCommandBuffer();
217 return CmdsParse(CommandTable, Cmd);