mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-12-27 10:34:08 +08:00
ab9f49f86e
Use longer timeout in WaitForRawDataTimeout() to handle CMD_WTX Fix a wrong type Apply changes to other similar part Remove unused instructions
196 lines
4.7 KiB
C
196 lines
4.7 KiB
C
//-----------------------------------------------------------------------------
|
|
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// See LICENSE.txt for the text of the license.
|
|
//-----------------------------------------------------------------------------
|
|
// Low frequency ZX8211 funtions
|
|
//-----------------------------------------------------------------------------
|
|
#include "lfzx.h"
|
|
#include "zx8211.h"
|
|
|
|
#include "BigBuf.h"
|
|
#include "crc.h" // CRC-8 / Hitag1 / ZX8211
|
|
#include "fpgaloader.h"
|
|
#include "dbprint.h"
|
|
#include "lfops.h" // turn_read_lf_on / off
|
|
#include "lfadc.h"
|
|
#include "lfsampling.h" // getSamplingConfig
|
|
#include "pm3_cmd.h" // struct
|
|
#include "ticks.h"
|
|
|
|
/*
|
|
ZX8211
|
|
|
|
RWE to tag
|
|
----------
|
|
ASK w 100% modulation index
|
|
When power field is:
|
|
off, its considered LOW field
|
|
on, its considered HIGH field
|
|
|
|
|
|
Binary Pulse Length Coding (BPLC)
|
|
|
|
ZERO = 8 off, 8 on (14-22)
|
|
ONE = 8 off, 28 on (26-32)
|
|
EOF = 8 off, 30 on (38 or more)
|
|
|
|
Protection
|
|
----------
|
|
32bit read password
|
|
32bit write password
|
|
|
|
Config bits
|
|
-------------
|
|
|
|
Timings
|
|
-------
|
|
|
|
Tx = 8us = 1fc
|
|
*/
|
|
|
|
#define ZX_START_GAP 170
|
|
#define ZX_WAIT_GAP 90
|
|
#define ZX_GAP 8 // 4 - 10
|
|
#define ZX_T0 18
|
|
#define ZX_T0_MIN 14
|
|
#define ZX_T0_MAX 22
|
|
#define ZX_T1 28
|
|
#define ZX_T1_MIN 26
|
|
#define ZX_T1_MAX 32
|
|
#define ZX_TEOF 38
|
|
#define ZX_RESET_GAP 35000 // 35ms
|
|
#define ZX_RESPONSE_GAP 208
|
|
|
|
#define ZX_PROG 716
|
|
#define ZX_PROG_CT 4470
|
|
|
|
// TTF switch to RTF
|
|
#define ZX_SWITCH_RTF 350
|
|
|
|
// ZX commands
|
|
#define LF_ZX_GET_UID 0b00110
|
|
#define LF_ZX_READ
|
|
#define LF_ZX_WRITE
|
|
|
|
|
|
static void zx8211_setup_read(void) {
|
|
|
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
|
|
|
// Make sure the tag is reset
|
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
|
|
|
// use lf config settings
|
|
sample_config *sc = getSamplingConfig();
|
|
LFSetupFPGAForADC(sc->divisor, true);
|
|
|
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
|
|
|
|
// 50ms for the resonant antenna to settle.
|
|
WaitMS(50);
|
|
|
|
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
|
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
|
|
|
|
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
|
|
|
|
// Connect the A/D to the peak-detected low-frequency path.
|
|
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
|
|
|
// Start the timer
|
|
StartTicks();
|
|
|
|
// Watchdog hit
|
|
WDT_HIT();
|
|
}
|
|
|
|
static void zx_send(const uint8_t *cmd, uint8_t clen) {
|
|
|
|
if (clen == 0)
|
|
return;
|
|
|
|
turn_read_lf_on(ZX_START_GAP);
|
|
|
|
// now start writing with bitbanging the antenna.
|
|
while (clen-- > 0) {
|
|
|
|
turn_read_lf_off(ZX_GAP * 8);
|
|
|
|
if (((*cmd++) & 1) == 1) {
|
|
turn_read_lf_on(ZX_T1 * 8);
|
|
} else {
|
|
turn_read_lf_on(ZX_T0 * 8);
|
|
}
|
|
}
|
|
|
|
// send eof
|
|
turn_read_lf_off(ZX_GAP * 8);
|
|
turn_read_lf_on(ZX_TEOF * 8);
|
|
}
|
|
|
|
static void zx_get(bool ledcontrol) {
|
|
|
|
while (BUTTON_PRESS() == false) {
|
|
|
|
WDT_HIT();
|
|
|
|
if (ledcontrol && (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY)) {
|
|
LED_D_ON();
|
|
}
|
|
|
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
|
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
|
(void)sample;
|
|
|
|
// (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope
|
|
if (ledcontrol) LED_D_OFF();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
int zx8211_read(zx8211_data_t *zxd, bool ledcontrol) {
|
|
zx8211_setup_read();
|
|
|
|
// clear buffer now so it does not interfere with timing later
|
|
BigBuf_Clear_ext(false);
|
|
|
|
if (ledcontrol) LED_A_ON();
|
|
|
|
// send GET_UID
|
|
zx_send(NULL, 0);
|
|
|
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
|
|
|
|
zx_get(ledcontrol);
|
|
|
|
//uint32_t cs = CRC8Hitag1(uint8_t *buff, size_t size);
|
|
|
|
if (ledcontrol) LEDsoff();
|
|
|
|
StopTicks();
|
|
lf_finalize(ledcontrol);
|
|
|
|
reply_ng(CMD_LF_ZX_READ, PM3_SUCCESS, NULL, 0);
|
|
return PM3_SUCCESS;
|
|
}
|
|
|
|
int zx8211_write(zx8211_data_t *zxd, bool ledcontrol) {
|
|
zx8211_setup_read();
|
|
|
|
StopTicks();
|
|
lf_finalize(ledcontrol);
|
|
//reply_ng(CMD_LF_ZX_WRITE, status, tag.data, sizeof(tag.data));
|
|
return PM3_SUCCESS;
|
|
}
|