1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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"
21 #include "cmdparser.h" // command_t
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");
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
);
59 static int CmdLFPCF7931Reader(const char *Cmd
) {
60 CLIParserContext
*ctx
;
61 CLIParserInit(&ctx
, "lf pcf7931 reader",
63 "lf pcf7931 reader -@ -> continuous reader mode"
68 arg_lit0("@", NULL
, "optional - continuous reader mode"),
71 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
72 bool cm
= arg_get_lit(ctx
, 1);
76 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
80 PacketResponseNG resp
;
82 SendCommandNG(CMD_LF_PCF7931_READ
, NULL
, 0);
83 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
84 PrintAndLogEx(WARNING
, "command execution time out");
87 } while (cm
&& !kbd_enter_pressed());
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"
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)"),
112 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
114 bool use_reset
= arg_get_lit(ctx
, 1);
117 return pcf7931_resetConfig();
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);
129 if (pwd_len
&& pwd_len
< sizeof(pwd
)) {
130 PrintAndLogEx(ERR
, "Password must be 7 bytes");
135 memcpy(configPcf
.Pwd
, pwd
, sizeof(configPcf
.Pwd
));
138 configPcf
.InitDelay
= (delay
& 0xFFFF);
141 configPcf
.OffsetWidth
= (ow
& 0xFFFF);
144 configPcf
.OffsetPosition
= (op
& 0xFFFF);
147 pcf7931_printConfig();
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 "
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"),
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);
171 uint8_t data
[1] = {0};
172 CLIGetHexWithReturn(ctx
, 3, data
, &data_len
);
176 PrintAndLogEx(ERR
, "out-of-range error, block must be between 0-7");
181 PrintAndLogEx(ERR
, "out-of-range error, index must be between 0-15");
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");
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
);
215 int CmdLFPCF7931(const char *Cmd
) {
216 clearCommandBuffer();
217 return CmdsParse(CommandTable
, Cmd
);