1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
3 // 2015 Dake <thomas.cayrou at gmail.com>
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
8 //-----------------------------------------------------------------------------
9 // Low frequency PCF7931 commands
10 //-----------------------------------------------------------------------------
11 #include "cmdlfpcf7931.h"
14 #include "cmdparser.h" // command_t
17 #include "cliparser.h"
19 static int CmdHelp(const char *Cmd
);
21 #define PCF7931_DEFAULT_INITDELAY 17500
22 #define PCF7931_DEFAULT_OFFSET_WIDTH 0
23 #define PCF7931_DEFAULT_OFFSET_POSITION 0
25 // Default values - Configuration
26 struct pcf7931_config configPcf
= {
27 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
28 PCF7931_DEFAULT_INITDELAY
,
29 PCF7931_DEFAULT_OFFSET_WIDTH
,
30 PCF7931_DEFAULT_OFFSET_POSITION
33 // Resets the configuration settings to default values.
34 int pcf7931_resetConfig(void) {
35 memset(configPcf
.Pwd
, 0xFF, sizeof(configPcf
.Pwd
));
36 configPcf
.InitDelay
= PCF7931_DEFAULT_INITDELAY
;
37 configPcf
.OffsetWidth
= PCF7931_DEFAULT_OFFSET_WIDTH
;
38 configPcf
.OffsetPosition
= PCF7931_DEFAULT_OFFSET_POSITION
;
39 PrintAndLogEx(INFO
, "Configuration resetted");
40 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf pcf7931 config`") " to view current settings");
44 int pcf7931_printConfig(void) {
45 PrintAndLogEx(INFO
, "Password (LSB first on bytes)... " _YELLOW_("%s"), sprint_hex(configPcf
.Pwd
, sizeof(configPcf
.Pwd
)));
46 PrintAndLogEx(INFO
, "Tag initialization delay........ " _YELLOW_("%d") " us", configPcf
.InitDelay
);
47 PrintAndLogEx(INFO
, "Offset low pulses width......... " _YELLOW_("%d") " us", configPcf
.OffsetWidth
);
48 PrintAndLogEx(INFO
, "Offset low pulses position...... " _YELLOW_("%d") " us", configPcf
.OffsetPosition
);
52 static int CmdLFPCF7931Reader(const char *Cmd
) {
53 CLIParserContext
*ctx
;
54 CLIParserInit(&ctx
, "lf pcf7931 reader",
56 "lf pcf7931 reader -@ -> continuous reader mode"
61 arg_lit0("@", NULL
, "optional - continuous reader mode"),
64 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
65 bool cm
= arg_get_lit(ctx
, 1);
69 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
73 PacketResponseNG resp
;
75 SendCommandNG(CMD_LF_PCF7931_READ
, NULL
, 0);
76 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
77 PrintAndLogEx(WARNING
, "command execution time out");
80 } while (cm
&& !kbd_enter_pressed());
85 static int CmdLFPCF7931Config(const char *Cmd
) {
86 CLIParserContext
*ctx
;
87 CLIParserInit(&ctx
, "lf pcf7931 config",
88 "This command tries to set the configuration used with PCF7931 commands\n"
89 "The time offsets could be useful to correct slew rate generated by the antenna\n"
90 "Caling without some parameter will print the current configuration.",
91 "lf pcf7931 config --reset\n"
92 "lf pcf7931 config --pwd 11223344556677 -d 20000\n"
93 "lf pcf7931 config --pwd 11223344556677 -d 17500 --lw -10 --lp 30"
98 arg_lit0("r", "reset", "Reset configuration to default values"),
99 arg_str0("p", "pwd", "<hex>", "Password, 7bytes, LSB-order"),
100 arg_u64_0("d", "delay", "<dec>", "Tag initialization delay (in us)"),
101 arg_int0(NULL
, "lw", "<dec>", "offset, low pulses width (in us)"),
102 arg_int0(NULL
, "lp", "<dec>", "offset, low pulses position (in us)"),
105 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
107 bool use_reset
= arg_get_lit(ctx
, 1);
110 return pcf7931_resetConfig();
114 uint8_t pwd
[7] = {0};
115 CLIGetHexWithReturn(ctx
, 2, pwd
, &pwd_len
);
117 uint32_t delay
= arg_get_u32_def(ctx
, 3, -1);
118 int ow
= arg_get_int_def(ctx
, 4, 0xFFFF);
119 int op
= arg_get_int_def(ctx
, 5, 0xFFFF);
122 if (pwd_len
&& pwd_len
< sizeof(pwd
)) {
123 PrintAndLogEx(ERR
, "Password must be 7 bytes");
128 memcpy(configPcf
.Pwd
, pwd
, sizeof(configPcf
.Pwd
));
131 configPcf
.InitDelay
= (delay
& 0xFFFF);
134 configPcf
.OffsetWidth
= (ow
& 0xFFFF);
137 configPcf
.OffsetPosition
= (op
& 0xFFFF);
140 pcf7931_printConfig();
144 static int CmdLFPCF7931Write(const char *Cmd
) {
146 CLIParserContext
*ctx
;
147 CLIParserInit(&ctx
, "lf pcf7931 write",
148 "This command tries to write a PCF7931 tag.",
149 "lf pcf7931 write --blk 2 --idx 1 -d FF -> Write 0xFF to block 2, index 1 "
154 arg_u64_1("b", "blk", "<dec>", "[0-7] block number"),
155 arg_u64_1("i", "idx", "<dec>", "[0-15] index of byte inside block"),
156 arg_str1("d", "data", "<hex>", "one byte to be written"),
159 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
160 uint8_t block
= arg_get_u32_def(ctx
, 1, 0);
161 uint8_t idx
= arg_get_u32_def(ctx
, 2, 0);
164 uint8_t data
[1] = {0};
165 CLIGetHexWithReturn(ctx
, 3, data
, &data_len
);
169 PrintAndLogEx(ERR
, "out-of-range error, block must be between 0-7");
174 PrintAndLogEx(ERR
, "out-of-range error, index must be between 0-15");
178 PrintAndLogEx(INFO
, "Writing block %u at idx %u with data 0x%02X", block
, idx
, data
[0]);
180 uint32_t buf
[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
181 memcpy(buf
, configPcf
.Pwd
, sizeof(configPcf
.Pwd
));
182 buf
[7] = (configPcf
.OffsetWidth
+ 128);
183 buf
[8] = (configPcf
.OffsetPosition
+ 128);
184 buf
[9] = configPcf
.InitDelay
;
186 clearCommandBuffer();
187 SendCommandMIX(CMD_LF_PCF7931_WRITE
, block
, idx
, data
[0], buf
, sizeof(buf
));
189 PrintAndLogEx(SUCCESS
, "Done");
190 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`lf pcf7931 reader`") " to verify");
194 static command_t CommandTable
[] = {
195 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
196 {"reader", CmdLFPCF7931Reader
, IfPm3Lf
, "Read content of a PCF7931 transponder"},
197 {"write", CmdLFPCF7931Write
, IfPm3Lf
, "Write data on a PCF7931 transponder."},
198 {"config", CmdLFPCF7931Config
, AlwaysAvailable
, "Configure the password, the tags initialization delay and time offsets (optional)"},
199 {NULL
, NULL
, NULL
, NULL
}
202 static int CmdHelp(const char *Cmd
) {
203 (void)Cmd
; // Cmd is not used so far
204 CmdsHelp(CommandTable
);
208 int CmdLFPCF7931(const char *Cmd
) {
209 clearCommandBuffer();
210 return CmdsParse(CommandTable
, Cmd
);