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 //----------------------------------------------------------------------------- 
  13 #include "proxmark3.h" 
  16 #include "cmdparser.h" 
  20 #include "cmdlfpcf7931.h" 
  22 static int CmdHelp(const char *Cmd
); 
  24 #define PCF7931_DEFAULT_INITDELAY 17500 
  25 #define PCF7931_DEFAULT_OFFSET_WIDTH 0 
  26 #define PCF7931_DEFAULT_OFFSET_POSITION 0 
  28 // Default values - Configuration 
  29 struct pcf7931_config configPcf 
= { 
  30         {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, 
  31         PCF7931_DEFAULT_INITDELAY
, 
  32         PCF7931_DEFAULT_OFFSET_WIDTH
,  
  33         PCF7931_DEFAULT_OFFSET_POSITION
 
  36 // Resets the configuration settings to default values. 
  37 int pcf7931_resetConfig(){ 
  38         memset(configPcf
.Pwd
, 0xFF, sizeof(configPcf
.Pwd
) ); 
  39         configPcf
.InitDelay 
= PCF7931_DEFAULT_INITDELAY
; 
  40         configPcf
.OffsetWidth 
= PCF7931_DEFAULT_OFFSET_WIDTH
;  
  41         configPcf
.OffsetPosition 
= PCF7931_DEFAULT_OFFSET_POSITION
;  
  45 int pcf7931_printConfig(){ 
  46         PrintAndLog("Password (LSB first on bytes) : %s", sprint_hex( configPcf
.Pwd
, sizeof(configPcf
.Pwd
))); 
  47         PrintAndLog("Tag initialization delay      : %d us", configPcf
.InitDelay
); 
  48         PrintAndLog("Offset low pulses width       : %d us", configPcf
.OffsetWidth
); 
  49         PrintAndLog("Offset low pulses position    : %d us", configPcf
.OffsetPosition
); 
  53 int usage_pcf7931_read(){ 
  54         PrintAndLog("Usage: lf pcf7931 read [h] "); 
  55         PrintAndLog("This command tries to read a PCF7931 tag."); 
  56         PrintAndLog("Options:"); 
  57         PrintAndLog("       h   This help"); 
  58         PrintAndLog("Examples:"); 
  59         PrintAndLog("      lf pcf7931 read"); 
  63 int usage_pcf7931_write(){ 
  64         PrintAndLog("Usage: lf pcf7931 write [h] <block address> <byte address> <data>"); 
  65         PrintAndLog("This command tries to write a PCF7931 tag."); 
  66         PrintAndLog("Options:"); 
  67         PrintAndLog("       h                      This help"); 
  68         PrintAndLog("       blockaddress   Block to save [0-7]"); 
  69         PrintAndLog("       byteaddress    Index of byte inside block to write [0-3]"); 
  70         PrintAndLog("       data           one byte of data (hex)"); 
  71         PrintAndLog("Examples:"); 
  72         PrintAndLog("      lf pcf7931 write 2 1 FF"); 
  76 int usage_pcf7931_config(){ 
  77         PrintAndLog("Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>"); 
  78         PrintAndLog("This command tries to set the configuration used with PCF7931 commands"); 
  79         PrintAndLog("The time offsets could be useful to correct slew rate generated by the antenna"); 
  80         PrintAndLog("Caling without some parameter will print the current configuration."); 
  81         PrintAndLog("Options:"); 
  82         PrintAndLog("       h       This help"); 
  83         PrintAndLog("       r       Reset configuration to default values"); 
  84         PrintAndLog("       pwd     Password, hex, 7bytes, LSB-order"); 
  85         PrintAndLog("       delay   Tag initialization delay (in us) decimal"); 
  86         PrintAndLog("       offset  Low pulses width (in us) decimal"); 
  87         PrintAndLog("       offset  Low pulses position (in us) decimal");       
  88         PrintAndLog("Examples:"); 
  89         PrintAndLog("      lf pcf7931 config"); 
  90         PrintAndLog("      lf pcf7931 config r"); 
  91         PrintAndLog("      lf pcf7931 config 11223344556677 20000"); 
  92         PrintAndLog("      lf pcf7931 config 11223344556677 17500 -10 30"); 
  96 int CmdLFPCF7931Read(const char *Cmd
){   
  98         uint8_t ctmp 
= param_getchar(Cmd
, 0); 
  99         if ( ctmp 
== 'H' || ctmp 
== 'h' ) return usage_pcf7931_read(); 
 102         UsbCommand c 
= {CMD_PCF7931_READ
, {0, 0, 0}}; 
 103         clearCommandBuffer(); 
 105         if ( !WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) ) { 
 106                 PrintAndLog("command execution time out"); 
 112 int CmdLFPCF7931Config(const char *Cmd
){  
 114         uint8_t ctmp 
= param_getchar(Cmd
, 0); 
 115         if ( ctmp 
== 0) return pcf7931_printConfig(); 
 116         if ( ctmp 
== 'H' || ctmp 
== 'h' ) return usage_pcf7931_config(); 
 117         if ( ctmp 
== 'R' || ctmp 
== 'r' ) return pcf7931_resetConfig();  
 119         if ( param_gethex(Cmd
, 0, configPcf
.Pwd
, 14) ) return usage_pcf7931_config(); 
 121         configPcf
.InitDelay 
= (param_get32ex(Cmd
,1,0,10) & 0xFFFF); 
 122         configPcf
.OffsetWidth 
= (int)(param_get32ex(Cmd
,2,0,10) & 0xFFFF); 
 123         configPcf
.OffsetPosition 
= (int)(param_get32ex(Cmd
,3,0,10) & 0xFFFF); 
 125         pcf7931_printConfig(); 
 129 int CmdLFPCF7931Write(const char *Cmd
){ 
 131         uint8_t ctmp 
= param_getchar(Cmd
, 0); 
 132         if (strlen(Cmd
) < 1 || ctmp 
== 'h' || ctmp 
== 'H') return usage_pcf7931_write();         
 134         uint8_t block 
= 0, bytepos 
= 0, data 
= 0; 
 136         if ( param_getdec(Cmd
, 0, &block
) ) return usage_pcf7931_write(); 
 137         if ( param_getdec(Cmd
, 1, &bytepos
) ) return usage_pcf7931_write(); 
 139         if ( (block 
> 7) || (bytepos 
> 3) ) return usage_pcf7931_write(); 
 141         data    
= param_get8ex(Cmd
, 2, 0, 16); 
 143         PrintAndLog("Writing block: %d", block
); 
 144         PrintAndLog("          pos: %d", bytepos
); 
 145         PrintAndLog("         data: 0x%02X", data
); 
 147         UsbCommand c 
= {CMD_PCF7931_WRITE
, { block
, bytepos
, data
} }; 
 148         memcpy(c
.d
.asDwords
, configPcf
.Pwd
, sizeof(configPcf
.Pwd
) ); 
 149     c
.d
.asDwords
[7] = (configPcf
.OffsetWidth 
+ 128); 
 150     c
.d
.asDwords
[8] = (configPcf
.OffsetPosition 
+ 128); 
 151     c
.d
.asDwords
[9] = configPcf
.InitDelay
; 
 153         clearCommandBuffer(); 
 159 static command_t CommandTable
[] =  
 161         {"help",        CmdHelp
,                        1, "This help"}, 
 162         {"read",        CmdLFPCF7931Read
,       1, "Read content of a PCF7931 transponder"}, 
 163         {"write",       CmdLFPCF7931Write
,      1, "Write data on a PCF7931 transponder."}, 
 164         {"config",      CmdLFPCF7931Config
, 1, "Configure the password, the tags initialization delay and time offsets (optional)"}, 
 165         {NULL
, NULL
, 0, NULL
} 
 168 int CmdLFPCF7931(const char *Cmd
) 
 170         CmdsParse(CommandTable
, Cmd
); 
 174 int CmdHelp(const char *Cmd
) 
 176         CmdsHelp(CommandTable
);