Merge pull request #575 from bosb/fix_hitags_sim

hitagS fix sim + write
This commit is contained in:
Iceman 2020-03-11 12:57:12 +01:00 committed by GitHub
commit d63d6d0978
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 212 additions and 415 deletions

View file

@ -434,6 +434,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk)
- Added `script run luxeodump` (@0xdrrb)
- Fix `lf hitag reader 02` - print all bytes (@bosb)
- Fix hitag S simulation (still not working), write, add example HITAG S 256 (@bosb)
### Fixed

View file

@ -10,6 +10,7 @@
//-----------------------------------------------------------------------------
// Some code was copied from Hitag2.c
//-----------------------------------------------------------------------------
// bosb 2020
#include "hitagS.h"
@ -23,6 +24,7 @@
#include "string.h"
#include "commonutil.h"
#include "hitag2_crypto.h"
#include "lfadc.h"
#define CRC_PRESET 0xFF
#define CRC_POLYNOM 0x1D
@ -50,6 +52,22 @@ size_t blocknr;
bool end = false;
//#define SENDBIT_TEST
/* array index 3 2 1 0 // bytes in sim.bin file are 0 1 2 3
// UID is 0 1 2 3 // tag.uid is 3210
// datasheet HitagS_V11.pdf bytes in tables printed 3 2 1 0
#db# UID: 5F C2 11 84
#db# conf0: C9 conf1: 00 conf2: 00
3 2 1 0
#db# Page[ 0]: 84 11 C2 5F uid
#db# Page[ 1]: AA 00 00 C9 conf, HITAG S 256
#db# Page[ 2]: 4E 4F 54 48
#db# Page[ 3]: 52 4B 49 4D
#db# Page[ 4]: 00 00 00 00
#db# Page[ 5]: 00 00 00 00
#db# Page[ 6]: 00 00 00 00
#db# Page[ 7]: 4B 4F 5F 57 */
#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
@ -86,7 +104,7 @@ bool end = false;
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
#define DEBUG 0
#define DBGLEVEL 0
/*
* Implementation of the crc8 calculation from Hitag S
@ -207,6 +225,22 @@ static void hitag_send_bit(int bit) {
}
static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("hitag_send_frame: (%i) %02X %02X %02X %02X", frame_len, frame[0], frame[1], frame[2], frame[3]);
// The beginning of the frame is hidden in some high level; pause until our bits will have an effect
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
HIGH(GPIO_SSC_DOUT);
switch (m) {
case AC4K:
case MC8K:
while (AT91C_BASE_TC0->TC_CV < T0 * 40) {}; //FADV
break;
case AC2K:
case MC4K:
while (AT91C_BASE_TC0->TC_CV < T0 * 20) {}; //STD + ADV
break;
}
// SOF - send start of frame
for (size_t i = 0; i < sof_bits; i++) {
hitag_send_bit(1);
@ -299,6 +333,25 @@ static int check_select(uint8_t *rx, uint32_t uid) {
return 0;
}
void hitagS_set_frame_modulation() {
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
}
/*
* handles all commands from a reader
*/
@ -318,20 +371,28 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
switch (rxlen) {
case 5: {
//UID request with a selected response protocol mode
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("UID request: length: %i first byte: %02x", rxlen, rx[0]);
tag.pstate = HT_READY;
tag.tstate = HT_NO_OP;
if ((rx[0] & 0xf0) == 0x30) {
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("HT_STANDARD");
tag.mode = HT_STANDARD;
sof_bits = 1;
m = AC2K;
}
if ((rx[0] & 0xf0) == 0xc0) {
tag.mode = HT_ADVANCED;
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("HT_ADVANCED");
sof_bits = 3;
m = AC2K;
}
if ((rx[0] & 0xf0) == 0xd0) {
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("HT_FAST_ADVANCED");
tag.mode = HT_FAST_ADVANCED;
sof_bits = 3;
m = AC4K;
@ -344,29 +405,18 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
break;
case 45: {
//select command from reader received
if (DBGLEVEL >= DBG_EXTENDED)
DbpString("SELECT");
if (check_select(rx, tag.uid) == 1) {
if (DBGLEVEL >= DBG_EXTENDED)
DbpString("SELECT match");
//if the right tag was selected
*txlen = 32;
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
//send configuration
for (int i = 0; i < 4; i++)
tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff;
tx[i] = tag.pages[1][i];
tx[3] = 0xff;
if (tag.mode != HT_STANDARD) {
*txlen = 40;
@ -390,22 +440,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
for (int i = 0; i < 4; i++)
_hitag2_byte(&state);
@ -438,7 +473,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
}
*/
}
break;
case 40:
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("WRITE");
//data received to be written
if (tag.tstate == HT_WRITING_PAGE_DATA) {
tag.tstate = HT_NO_OP;
@ -448,44 +486,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
*txlen = 2;
tx[0] = 0x40;
page_to_be_written = 0;
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
} else if (tag.tstate == HT_WRITING_BLOCK_DATA) {
tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
<< 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
//send ack
*txlen = 2;
tx[0] = 0x40;
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
page_to_be_written++;
block_data_left--;
if (block_data_left == 0) {
@ -500,29 +508,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
//send page data
uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
*txlen = 32;
tx[0] = (tag.pages[page / 4][page % 4]) & 0xff;
tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
tx[0] = tag.pages[page][0];
tx[1] = tag.pages[page][1];
tx[2] = tag.pages[page][2];
tx[3] = tag.pages[page][3];
if (tag.LKP && page == 1)
tx[3] = 0xff;
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
if (tag.mode != HT_STANDARD) {
//add crc8
@ -543,29 +536,13 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
*txlen = 32 * 4;
//send page,...,page+3 data
for (int i = 0; i < 4; i++) {
tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff;
tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
page++;
tx[0 + i * 4] = tag.pages[page + 0 + i * 4][0];
tx[1 + i * 4] = tag.pages[page + 1 + i * 4][1];
tx[2 + i * 4] = tag.pages[page + 2 + i * 4][2];
tx[3 + i * 4] = tag.pages[page + 3 + i * 4][3];
}
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
if (tag.mode != HT_STANDARD) {
//add crc8
@ -576,29 +553,12 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
tx[16] = crc;
}
if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) {
if ((page) % 4 != 0 || (tag.LKP && (page) == 0)) {
sof_bits = 0;
*txlen = 0;
}
} else if ((rx[0] & 0xf0) == 0x80) { //write page
uint8_t page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
if ((tag.LCON && page == 1)
|| (tag.LKP && (page == 2 || page == 3))) {
//deny
@ -613,22 +573,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
} else if ((rx[0] & 0xf0) == 0x90) { //write block
uint8_t page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
switch (tag.mode) {
case HT_STANDARD:
sof_bits = 1;
m = MC4K;
break;
case HT_ADVANCED:
sof_bits = 6;
m = MC4K;
break;
case HT_FAST_ADVANCED:
sof_bits = 6;
m = MC8K;
break;
default:
break;
}
hitagS_set_frame_modulation();
if (page % 4 != 0 || page == 0) {
//deny
*txlen = 0;
@ -644,7 +589,8 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen,
}
break;
default:
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("unknown rxlen: (%i) %02X %02X %02X %02X ...", rxlen, rx[0], rx[1], rx[2], rx[3]);
break;
}
}
@ -722,7 +668,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
| (uid[30] << 1)
| uid[31];
if (DEBUG)
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4);
tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1);
@ -816,7 +762,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
tag.LCK1 = response_bit[26];
tag.LCK0 = response_bit[27];
if (DEBUG)
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]);
if (tag.auth == 1) {
@ -839,7 +785,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
tx[5] = auth_ks[1];
tx[6] = auth_ks[2];
tx[7] = auth_ks[3];
if (DEBUG)
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
} else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
@ -864,7 +810,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8);
calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8);
calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8);
if (DEBUG) {
if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("UID:::%X", tag.uid);
Dbprintf("RND:::%X", rnd);
}
@ -884,7 +830,7 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA
pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state);
}
if (DEBUG)
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1);
//Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16));
@ -930,28 +876,30 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
tag.pstate = HT_READY;
tag.tstate = HT_NO_OP;
for (i = 0; i < 16; i++)
for (j = 0; j < 4; j++)
tag.pages[i][j] = 0x0;
// read tag data into memory
if (tag_mem_supplied) {
for (i = 0; i < 16; i++)
for (j = 0; j < 4; j++)
tag.pages[i][j] = 0x0;
DbpString("Loading hitagS memory...");
memcpy((uint8_t *)tag.pages, data, 4 * 64);
} else {
// use the last read tag
}
tag.uid = (uint32_t)tag.pages[0];
tag.key = (intptr_t)tag.pages[3];
tag.uid = (tag.pages[0][3] << 24 | tag.pages[0][2] << 16 | tag.pages[0][1] << 8 | tag.pages[0][0]);
tag.key = (tag.pages[3][3] << 24 | tag.pages[3][2] << 16 | tag.pages[3][1] << 8 | tag.pages[3][0]);
tag.key <<= 16;
tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1];
tag.pwdl0 = tag.pages[2][3];
tag.pwdl1 = tag.pages[2][2];
tag.pwdh0 = tag.pages[1][0];
tag.key += ((tag.pages[2][3]) << 8) + tag.pages[2][2];
tag.pwdl0 = tag.pages[2][0];
tag.pwdl1 = tag.pages[2][1];
tag.pwdh0 = tag.pages[1][3];
//con0
tag.max_page = 64;
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 1)
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1)
tag.max_page = 8;
if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0)
if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0)
tag.max_page = 0;
if (DBGLEVEL >= DBG_EXTENDED)
for (i = 0; i < tag.max_page; i++)
@ -962,41 +910,42 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
tag.pages[i][0] & 0xff);
//con1
tag.auth = 0;
if ((tag.pages[1][2] & 0x80) == 0x80)
if ((tag.pages[1][1] & 0x80) == 0x80)
tag.auth = 1;
tag.LCON = 0;
if ((tag.pages[1][2] & 0x2) == 0x02)
if ((tag.pages[1][1] & 0x2) == 0x02)
tag.LCON = 1;
tag.LKP = 0;
if ((tag.pages[1][2] & 0x1) == 0x01)
if ((tag.pages[1][1] & 0x1) == 0x01)
tag.LKP = 1;
//con2
//0=read write 1=read only
tag.LCK7 = 0;
if ((tag.pages[1][1] & 0x80) == 0x80)
if ((tag.pages[1][2] & 0x80) == 0x80)
tag.LCK7 = 1;
tag.LCK6 = 0;
if ((tag.pages[1][1] & 0x40) == 0x040)
if ((tag.pages[1][2] & 0x40) == 0x040)
tag.LCK6 = 1;
tag.LCK5 = 0;
if ((tag.pages[1][1] & 0x20) == 0x20)
if ((tag.pages[1][2] & 0x20) == 0x20)
tag.LCK5 = 1;
tag.LCK4 = 0;
if ((tag.pages[1][1] & 0x10) == 0x10)
if ((tag.pages[1][2] & 0x10) == 0x10)
tag.LCK4 = 1;
tag.LCK3 = 0;
if ((tag.pages[1][1] & 0x8) == 0x08)
if ((tag.pages[1][2] & 0x8) == 0x08)
tag.LCK3 = 1;
tag.LCK2 = 0;
if ((tag.pages[1][1] & 0x4) == 0x04)
if ((tag.pages[1][2] & 0x4) == 0x04)
tag.LCK2 = 1;
tag.LCK1 = 0;
if ((tag.pages[1][1] & 0x2) == 0x02)
if ((tag.pages[1][2] & 0x2) == 0x02)
tag.LCK1 = 1;
tag.LCK0 = 0;
if ((tag.pages[1][1] & 0x1) == 0x01)
if ((tag.pages[1][2] & 0x1) == 0x01)
tag.LCK0 = 1;
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -1028,7 +977,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on rising edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
| AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
| AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
// Enable and reset counter
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
@ -1100,12 +1049,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
}
// Enable and reset external trigger in timer for capturing future frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Reset the received frame and response timing info
memset(rx, 0x00, sizeof(rx));
response = 0;
// Enable and reset external trigger in timer for capturing future frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
LED_B_OFF();
}
// Reset the frame length
@ -1114,22 +1064,92 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) {
overflow += (AT91C_BASE_TC1->TC_CV / T0);
// Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
}
LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
lf_finalize();
// release allocated memory from BigBuff.
BigBuf_free();
StartTicks();
DbpString("Sim Stopped");
}
void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response) {
// Reset values for receiving frames
memset(rx, 0x00, HITAG_FRAME_LEN * sizeof(uint8_t));
*rxlen = 0;
int lastbit = 1;
bool bSkip = true;
int tag_sof = 1;
*response = 0;
uint32_t errorCount = 0;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA / T0);
// Reset timer every frame, we have to capture the last edge for timing
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
if (ra >= HITAG_T_EOF) {
if (*rxlen != 0) {
//DbpString("wierd1?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
*response = ra - HITAG_T_TAG_HALF_PERIOD;
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8));
(*rxlen)++;
rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8));
(*rxlen)++;
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8));
(*rxlen)++;
// We have to skip this half period at start and add the 'one' the second time
if (!bSkip) {
rx[(*rxlen) / 8] |= 1 << (7 - ((*rxlen) % 8));
(*rxlen)++;
}
lastbit = !lastbit;
bSkip = !bSkip;
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
if (tag_sof) {
// Ignore bits that are transmitted during SOF
tag_sof--;
} else {
// bit is same as last bit
rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8));
(*rxlen)++;
}
} else {
// Ignore wierd value, is to small to mean anything
errorCount++;
}
}
// if we saw over 100 wierd values break it probably isn't hitag...
if (errorCount > 100) break;
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
if ((*rxlen) > 0)
break;
}
}
}
/*
* Authenticates to the Tag with the given key or challenge.
* If the key was given the password will be decrypted.
@ -1149,7 +1169,6 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
uint8_t *tx = txbuf;
size_t txlen = 0;
int lastbit = 1;
int reset_sof = 1;
int t_wait = HITAG_T_WAIT_MAX;
bool bStop = false;
int pageNum = 0;
@ -1164,6 +1183,9 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
uint64_t NrAr = 0;
uint8_t key_[6];
tag.pstate = HT_READY;
tag.tstate = HT_NO_OP;
switch (htf) {
case RHTSF_CHALLENGE: {
DbpString("Authenticating using nr,ar pair:");
@ -1238,10 +1260,8 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
// synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
// Reset the received frame, frame count and timing info
t_wait = 200;
while (!bStop && !BUTTON_PRESS() && !data_available()) {
WDT_HIT();
@ -1381,85 +1401,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) {
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
}
// Reset values for receiving frames
memset(rx, 0x00, sizeof(rx));
rxlen = 0;
lastbit = 1;
bool bSkip = true;
int tag_sof = reset_sof;
response = 0;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA / T0);
// Reset timer every frame, we have to capture the last edge for timing
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//DbpString("wierd1?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
response = ra - HITAG_T_TAG_HALF_PERIOD;
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
// We have to skip this half period at start and add the 'one' the second time
if (!bSkip) {
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
}
lastbit = !lastbit;
bSkip = !bSkip;
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
if (tag_sof) {
// Ignore bits that are transmitted during SOF
tag_sof--;
} else {
// bit is same as last bit
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
rxlen++;
}
} else {
// Ignore wierd value, is to small to mean anything
}
}
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
if (rxlen > 0)
break;
}
}
hitagS_receive_frame(rx, &rxlen, &response);
}
end = false;
LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
StartTicks();
lf_finalize();
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
}
@ -1479,7 +1426,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
uint8_t *tx = txbuf;
size_t txlen = 0;
int lastbit;
int reset_sof;
int t_wait = HITAG_T_WAIT_MAX;
bool bStop;
unsigned char crc;
@ -1555,6 +1501,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
// external trigger rising edge, load RA on falling edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
| AT91C_TC_ETRGEDG_FALLING
@ -1570,7 +1517,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
// Reset the received frame, frame count and timing info
lastbit = 1;
bStop = false;
reset_sof = 1;
t_wait = 200;
while (!bStop && !BUTTON_PRESS() && !data_available()) {
@ -1670,87 +1616,13 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) {
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
}
// Reset values for receiving frames
memset(rx, 0x00, sizeof(rx));
rxlen = 0;
lastbit = 1;
bool bSkip = true;
int tag_sof = reset_sof;
response = 0;
uint32_t errorCount = 0;
hitagS_receive_frame(rx, &rxlen, &response);
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA / T0);
// Reset timer every frame, we have to capture the last edge for timing
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//DbpString("wierd1?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
response = ra - HITAG_T_TAG_HALF_PERIOD;
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
// We have to skip this half period at start and add the 'one' the second time
if (!bSkip) {
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
}
lastbit = !lastbit;
bSkip = !bSkip;
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
if (tag_sof) {
// Ignore bits that are transmitted during SOF
tag_sof--;
} else {
// bit is same as last bit
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
rxlen++;
}
} else {
// Ignore wierd value, is to small to mean anything
errorCount++;
}
}
// if we saw over 100 wierd values break it probably isn't hitag...
if (errorCount > 100) break;
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
if (rxlen > 0)
break;
}
}
}
end = false;
LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
StartTicks();
lf_finalize();
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
}
@ -1773,7 +1645,7 @@ void check_challenges(bool file_given, uint8_t *data) {
size_t rxlen = 0;
uint8_t txbuf[HITAG_FRAME_LEN];
int t_wait = HITAG_T_WAIT_MAX;
int lastbit, reset_sof, STATE = 0;;
int lastbit, STATE = 0;;
bool bStop;
int response_bit[200];
unsigned char mask = 1;
@ -1834,7 +1706,6 @@ void check_challenges(bool file_given, uint8_t *data) {
// Reset the received frame, frame count and timing info
lastbit = 1;
bStop = false;
reset_sof = 1;
t_wait = 200;
if (file_given) {
@ -1984,85 +1855,10 @@ void check_challenges(bool file_given, uint8_t *data) {
LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true);
}
// Reset values for receiving frames
memset(rx, 0x00, sizeof(rx));
rxlen = 0;
lastbit = 1;
bool bSkip = true;
int tag_sof = reset_sof;
response = 0;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA / T0);
// Reset timer every frame, we have to capture the last edge for timing
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//DbpString("wierd1?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
response = ra - HITAG_T_TAG_HALF_PERIOD;
} else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
} else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
rxlen++;
// We have to skip this half period at start and add the 'one' the second time
if (!bSkip) {
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
rxlen++;
}
lastbit = !lastbit;
bSkip = !bSkip;
} else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
if (tag_sof) {
// Ignore bits that are transmitted during SOF
tag_sof--;
} else {
// bit is same as last bit
rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
rxlen++;
}
} else {
// Ignore wierd value, is to small to mean anything
}
}
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
if (rxlen > 0)
break;
}
}
hitagS_receive_frame(rx, &rxlen, &response);
}
LEDsoff();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
set_tracing(false);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
StartTicks();
lf_finalize();
reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0);
}