fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / cmdlfpcf7931.c
blobbd744f8baefea93f842336d615d6528c038f1ef0
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
7 // the license.
8 //-----------------------------------------------------------------------------
9 // Low frequency PCF7931 commands
10 //-----------------------------------------------------------------------------
11 #include "cmdlfpcf7931.h"
12 #include <string.h>
13 #include <ctype.h>
14 #include "cmdparser.h" // command_t
15 #include "comms.h"
16 #include "ui.h"
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");
41 return PM3_SUCCESS;
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);
49 return PM3_SUCCESS;
52 static int CmdLFPCF7931Reader(const char *Cmd) {
53 CLIParserContext *ctx;
54 CLIParserInit(&ctx, "lf pcf7931 reader",
55 "read a PCF7931 tag",
56 "lf pcf7931 reader -@ -> continuous reader mode"
59 void *argtable[] = {
60 arg_param_begin,
61 arg_lit0("@", NULL, "optional - continuous reader mode"),
62 arg_param_end
64 CLIExecWithReturn(ctx, Cmd, argtable, true);
65 bool cm = arg_get_lit(ctx, 1);
66 CLIParserFree(ctx);
68 if (cm) {
69 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
72 do {
73 PacketResponseNG resp;
74 clearCommandBuffer();
75 SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
76 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
77 PrintAndLogEx(WARNING, "command execution time out");
78 return PM3_ETIMEOUT;
80 } while (cm && !kbd_enter_pressed());
82 return PM3_SUCCESS;
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"
96 void *argtable[] = {
97 arg_param_begin,
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)"),
103 arg_param_end
105 CLIExecWithReturn(ctx, Cmd, argtable, true);
107 bool use_reset = arg_get_lit(ctx, 1);
108 if (use_reset) {
109 CLIParserFree(ctx);
110 return pcf7931_resetConfig();
113 int pwd_len = 0;
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);
120 CLIParserFree(ctx);
122 if (pwd_len && pwd_len < sizeof(pwd)) {
123 PrintAndLogEx(ERR, "Password must be 7 bytes");
124 return PM3_EINVARG;
127 if (pwd_len) {
128 memcpy(configPcf.Pwd, pwd, sizeof(configPcf.Pwd));
130 if (delay != -1) {
131 configPcf.InitDelay = (delay & 0xFFFF);
133 if (ow != 0xFFFF) {
134 configPcf.OffsetWidth = (ow & 0xFFFF);
136 if (op != 0xFFFF) {
137 configPcf.OffsetPosition = (op & 0xFFFF);
140 pcf7931_printConfig();
141 return PM3_SUCCESS;
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 "
152 void *argtable[] = {
153 arg_param_begin,
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"),
157 arg_param_end
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);
163 int data_len = 0;
164 uint8_t data[1] = {0};
165 CLIGetHexWithReturn(ctx, 3, data, &data_len);
166 CLIParserFree(ctx);
168 if (block > 7) {
169 PrintAndLogEx(ERR, "out-of-range error, block must be between 0-7");
170 return PM3_EINVARG;
173 if (idx > 15) {
174 PrintAndLogEx(ERR, "out-of-range error, index must be between 0-15");
175 return PM3_EINVARG;
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");
191 return PM3_SUCCESS;
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);
205 return PM3_SUCCESS;
208 int CmdLFPCF7931(const char *Cmd) {
209 clearCommandBuffer();
210 return CmdsParse(CommandTable, Cmd);