forked from RfidResearchGroup/proxmark3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlfzx.c
196 lines (144 loc) · 4.68 KB
/
lfzx.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//-----------------------------------------------------------------------------
// 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;
}