add : writing on PCF7931 tags

This commit is contained in:
Dake 2015-08-26 15:53:49 +02:00
parent 5d01f50ae1
commit dc4300bafb
6 changed files with 388 additions and 7 deletions

View file

@ -987,6 +987,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
ReadPCF7931();
cmd_send(CMD_ACK,0,0,0,0,0);
break;
case CMD_PCF7931_WRITE:
WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]);
break;
case CMD_EM4X_READ_WORD:
EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]);
break;

View file

@ -61,6 +61,7 @@ void AcquireRawAdcSamples125k(int divisor);
void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command);
void ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void);
void AcquireRawBitsTI(void);
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
@ -85,6 +86,11 @@ int DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block);
int IsBlock1PCF7931(uint8_t *Block);
void ReadPCF7931();
void SendCmdPCF7931(uint32_t * tab);
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p);
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab);
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data);
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);

View file

@ -16,8 +16,7 @@
#include "string.h"
#include "lfdemod.h"
#include "lfsampling.h"
#include "usb_cdc.h"
#include "usb_cdc.h" //test
/**
* Function to do a modulation and then get samples.
@ -214,6 +213,8 @@ void ReadTItag(void)
}
}
void WriteTIbyte(uint8_t b)
{
int i = 0;
@ -310,12 +311,17 @@ void AcquireTiType(void)
}
}
// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
// if crc provided, it will be written with the data verbatim (even if bogus)
// if not provided a valid crc will be computed from the data and written.
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
{
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if(crc == 0) {
crc = update_crc16(crc, (idlo)&0xff);
crc = update_crc16(crc, (idlo>>8)&0xff);
@ -1705,6 +1711,8 @@ int DemodPCF7931(uint8_t **outBlocks) {
if(num_blocks == 4) break;
}
memcpy(outBlocks, Blocks, 16*num_blocks);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return num_blocks;
}
@ -1828,14 +1836,21 @@ void ReadPCF7931() {
Dbprintf("Memory content:");
Dbprintf("-----------------------------------------");
for(i=0; i<max_blocks; i++) {
if(Blocks[i][ALLOC]==1)
if(Blocks[i][ALLOC]==1){
Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7],
Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]);
else
if(i==3){
if(Blocks[3][0] == 0xAA)
Dbprintf("Solde actuel : %d centimes, solde précédent : %d centimes", (Blocks[3][1] << 8 | Blocks[3][2]), (Blocks[3][6] << 8 | Blocks[3][7]));
else
Dbprintf("Solde actuel : %d centimes, solde précédent : %d centimes", (Blocks[3][6] << 8 | Blocks[3][7]), (Blocks[3][1] << 8 | Blocks[3][2]));
}
}else
Dbprintf("<missing block %d>", i);
}
Dbprintf("-----------------------------------------");
return ;
}
@ -2058,3 +2073,261 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
}
#define T0_PCF 8 //period for the pcf7931 in us
/* Write on a byte of a PCF7931 tag
* @param address : address of the block to write
@param byte : address of the byte to write
@param data : data to write
*/
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
{
uint32_t tab[1024]={0}; // data times frame
uint32_t u = 0;
uint8_t parity = 0;
bool comp = 0;
//BUILD OF THE DATA FRAME
//alimentation of the tag (time for initializing)
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
//PMC
Dbprintf("Initialization delay : %d us", init_delay);
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
//password indication bit
AddBitPCF7931(1, tab, l, p);
//password (on 56 bits)
Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7);
AddBytePCF7931(pass1, tab, l, p);
AddBytePCF7931(pass2, tab, l, p);
AddBytePCF7931(pass3, tab, l, p);
AddBytePCF7931(pass4, tab, l, p);
AddBytePCF7931(pass5, tab, l, p);
AddBytePCF7931(pass6, tab, l, p);
AddBytePCF7931(pass7, tab, l, p);
//programming mode (0 or 1)
AddBitPCF7931(0, tab, l, p);
//block adress on 6 bits
Dbprintf("Block address : %02x", address);
for (u=0; u<6; u++)
{
if (address&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ // bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//byte address on 4 bits
Dbprintf("Byte address : %02x", byte);
for (u=0; u<4; u++)
{
if (byte&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ // bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//data on 8 bits
Dbprintf("Data : %02x", data);
for (u=0; u<8; u++)
{
if (data&(1<<u)) { // bit 1
parity++;
AddBitPCF7931(1, tab, l, p);
} else{ //bit 0
AddBitPCF7931(0, tab, l, p);
}
}
//parity bit
if((parity%2)==0){
AddBitPCF7931(0, tab, l, p); //even parity
}else{
AddBitPCF7931(1, tab, l, p);//odd parity
}
//time access memory
AddPatternPCF7931(5120+2680, 0, 0, tab);
//conversion of the scale time
for(u=0;u<500;u++){
tab[u]=(tab[u] * 3)/2;
}
//compennsation of the counter reload
while (!comp){
comp = 1;
for(u=0;tab[u]!=0;u++){
if(tab[u] > 0xFFFF){
tab[u] -= 0xFFFF;
comp = 0;
}
}
}
SendCmdPCF7931(tab);
}
/* Send a trame to a PCF7931 tags
* @param tab : array of the data frame
*/
void SendCmdPCF7931(uint32_t * tab){
uint16_t u=0;
uint16_t tempo=0;
Dbprintf("SENDING DATA FRAME...");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
LED_A_ON();
// steal this pin from the SSP and use it to control the modulation
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
//initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
AT91C_BASE_TCB->TCB_BCR = 1;
tempo = AT91C_BASE_TC0->TC_CV;
for(u=0;tab[u]!= 0;u+=3){
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u]){
tempo = AT91C_BASE_TC0->TC_CV;
}
// stop modulating antenna
LOW(GPIO_SSC_DOUT);
while(tempo != tab[u+1]){
tempo = AT91C_BASE_TC0->TC_CV;
}
// modulate antenna
HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u+2]){
tempo = AT91C_BASE_TC0->TC_CV;
}
}
LED_A_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200);
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
DbpString("FINISH !");
DbpString("(Could be usefull to send the same trame many times)");
LED(0xFFFF, 1000);
}
/* Add a byte for building the data frame of PCF7931 tags
* @param b : byte to add
* @param tab : array of the data frame
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
uint32_t u;
for (u=0; u<8; u++)
{
if (byte&(1<<u)) { //bit à 1
if(AddBitPCF7931(1, tab, l, p)==1)return 1;
} else { //bit à 0
if(AddBitPCF7931(0, tab, l, p)==1)return 1;
}
}
return 0;
}
/* Add a bits for building the data frame of PCF7931 tags
* @param b : bit to add
* @param tab : array of the data frame
* @param l : offset on low pulse width
* @param p : offset on low pulse positioning
*/
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
uint8_t u = 0;
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
if(b==1){ //add a bit 1
if(u==0) tab[u] = 34*T0_PCF+p;
else tab[u] = 34*T0_PCF+tab[u-1]+p;
tab[u+1] = 6*T0_PCF+tab[u]+l;
tab[u+2] = 88*T0_PCF+tab[u+1]-l-p;
return 0;
}else{ //add a bit 0
if(u==0) tab[u] = 98*T0_PCF+p;
else tab[u] = 98*T0_PCF+tab[u-1]+p;
tab[u+1] = 6*T0_PCF+tab[u]+l;
tab[u+2] = 24*T0_PCF+tab[u+1]-l-p;
return 0;
}
return 1;
}
/* Add a custom pattern in the data frame
* @param a : delay of the first high pulse
* @param b : delay of the low pulse
* @param c : delay of the last high pulse
* @param tab : array of the data frame
*/
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
uint32_t u = 0;
for(u=0;tab[u]!=0;u+=3){} //we put the cursor at the last value of the array
if(u==0) tab[u] = a;
else tab[u] = a + tab[u-1];
tab[u+1] = b+tab[u];
tab[u+2] = c+tab[u+1];
return 0;
}

View file

@ -1,6 +1,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
//
// 2015 Dake <thomas.cayrou at gmail.com>
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
@ -21,6 +22,8 @@
static int CmdHelp(const char *Cmd);
struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}};
int CmdLFPCF7931Read(const char *Cmd)
{
UsbCommand c = {CMD_PCF7931_READ};
@ -30,10 +33,93 @@ int CmdLFPCF7931Read(const char *Cmd)
return 0;
}
int CmdLFPCF7931Config(const char *Cmd)
{
int res = 0;
res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]);
if (res >= 7 || res < 1){
if(res == 7) configPcf.init_delay = 17500; //default value
if(res<=8){
configPcf.offset[0] = -10; //default value
configPcf.offset[1] = 30; //default value
}
if(res < 1){
PrintAndLog("Usage: <password byte 1 (in hex, lsb first)> <password byte 2 (in hex, lsb first)> [...] <password byte 7 (in hex, lsb first)> <tag initialization delay (in us)> <optional : offset on the low pulses width (in us)> <optional : offset on the low pulses position (in us)>");
PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna.");
}
PrintAndLog("Current configuration :");
PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]);
PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay);
PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]);
return 0;
}
//default values
configPcf.password[0] = 0xFF;
configPcf.password[1] = 0xFF;
configPcf.password[2] = 0xFF;
configPcf.password[3] = 0xFF;
configPcf.password[4] = 0xFF;
configPcf.password[5] = 0xFF;
configPcf.password[6] = 0xFF;
configPcf.init_delay = 17500;
configPcf.offset[0] = 0;
configPcf.offset[1] = 0;
PrintAndLog("Incorrect format");
PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000");
PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30");
return 0;
}
int CmdLFPCF7931Write(const char *Cmd)
{
UsbCommand c = {CMD_PCF7931_WRITE};
int res = 0;
res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]);
if(res < 1) {
PrintAndLog("Please specify the block address in hex");
return 0;
}
if (res == 1){
PrintAndLog("Please specify the byte address in hex");
return 0;
}
if(res == 2) {
PrintAndLog("Please specify the data in hex (1 byte)");
return 0;
}
if(res == 3) {
uint8_t n=0;
for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n];
c.d.asDwords[7] = (configPcf.offset[0]+128);
c.d.asDwords[8] = (configPcf.offset[1]+128);
c.d.asDwords[9] = configPcf.init_delay;
SendCommand(&c);
return 0;
}
PrintAndLog("INCORRECT FORMAT");
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"},
{"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write <bloc address> <byte address> <data>"},
{"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"},
{NULL, NULL, 0, NULL}
};

View file

@ -1,6 +1,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
//
// 2015 Dake <thomas.cayrou at gmail.com>
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
@ -11,8 +12,18 @@
#ifndef CMDLFPCF7931_H__
#define CMDLFPCF7931_H__
struct pcf7931_config{
uint8_t password[7];
uint16_t init_delay;
int16_t offset[2];
};
int CmdLFPCF7931(const char *Cmd);
int CmdLFPCF7931Read(const char *Cmd);
int CmdLFPCF7931Write(const char *Cmd);
int CmdLFPCF7931Config(const char *Cmd);
#endif

View file

@ -87,6 +87,7 @@ typedef struct{
#define CMD_T55XX_WRITE_BLOCK 0x0215
#define CMD_T55XX_READ_TRACE 0x0216
#define CMD_PCF7931_READ 0x0217
#define CMD_PCF7931_WRITE 0x0222
#define CMD_EM4X_READ_WORD 0x0218
#define CMD_EM4X_WRITE_WORD 0x0219
#define CMD_IO_DEMOD_FSK 0x021A
@ -99,6 +100,7 @@ typedef struct{
#define CMD_PSK_SIM_TAG 0x0220
#define CMD_AWID_DEMOD_FSK 0x0221
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
// For the 13.56 MHz tags