From 469e2dffec3395664ee09a7f55cea49212a8cf84 Mon Sep 17 00:00:00 2001 From: SG Date: Wed, 5 May 2021 17:50:19 +1000 Subject: [PATCH] [FL-1057] Low frequency RFID app [HID Encoder] (#445) * App Lfrfid: hid26 timer stage * App Lfrfid: hid26 encoder * fully removed old lf-rfid app * fix codeowners --- .github/CODEOWNERS | 4 + applications/lf-rfid-old/em4100.c | 71 ----------- applications/lf-rfid/helpers/encoder-hid.cpp | 118 +++++++++++++++++- applications/lf-rfid/helpers/encoder-hid.h | 7 +- .../lf-rfid/helpers/rfid-timer-emulator.cpp | 3 +- 5 files changed, 127 insertions(+), 76 deletions(-) delete mode 100644 applications/lf-rfid-old/em4100.c diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c0377666..96d7194e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -78,6 +78,10 @@ lib/onewire/** @DrZlo13 applications/irda/** @DrZlo13 +# LF-Rfid + +applications/lf-rfid/** @DrZlo13 + # Menu applications/menu/** @skotopes diff --git a/applications/lf-rfid-old/em4100.c b/applications/lf-rfid-old/em4100.c deleted file mode 100644 index 5c50a345..00000000 --- a/applications/lf-rfid-old/em4100.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include - -void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) { - uint8_t value[10]; - - // vendor rows (4 bit in a row) - value[0] = (VENDOR >> 4) & 0xF; - value[1] = VENDOR & 0xF; - - const uint8_t ROW_SIZE = 4; - const uint8_t HEADER_SIZE = 9; - - // ID rows (4 bit in a row) - for(int i = 0; i < 8; i++) { - value[i + 2] = (ID >> (28 - i * ROW_SIZE)) & 0xF; - } - - for(uint8_t i = 0; i < HEADER_SIZE; i++) { - data[i] = 1; // header - } - - for(uint8_t i = 0; i < 10; i++) { // data - for(uint8_t j = 0; j < ROW_SIZE; j++) { - data[HEADER_SIZE + i * (ROW_SIZE + 1) + j] = (value[i] >> ((ROW_SIZE - 1) - j)) & 1; - } - - // row parity - data[HEADER_SIZE + i * (ROW_SIZE + 1) + ROW_SIZE] = - (data[HEADER_SIZE + i * (ROW_SIZE + 1) + 0] + - data[HEADER_SIZE + i * (ROW_SIZE + 1) + 1] + - data[HEADER_SIZE + i * (ROW_SIZE + 1) + 2] + - data[HEADER_SIZE + i * (ROW_SIZE + 1) + 3]) % - 2; - } - - for(uint8_t i = 0; i < ROW_SIZE; i++) { //checksum - uint8_t checksum = 0; - for(uint8_t j = 0; j < 10; j++) { - checksum += data[HEADER_SIZE + i + j * (ROW_SIZE + 1)]; - } - data[i + 59] = checksum % 2; - } - - data[63] = 0; // stop bit - - /* - printf("em data: "); - for(uint8_t i = 0; i < 64; i++) { - printf("%d ", data[i]); - } - printf("\r\n"); - */ -} - -void em4100_emulation(uint8_t* data, GpioPin* pin) { - taskENTER_CRITICAL(); - hal_gpio_write(pin, true); - - for(uint8_t i = 0; i < 8; i++) { - for(uint8_t j = 0; j < 64; j++) { - delay_us(260); - hal_gpio_write(pin, data[j]); - delay_us(260); - hal_gpio_write(pin, !data[j]); - } - } - - hal_gpio_write(pin, false); - taskEXIT_CRITICAL(); -} diff --git a/applications/lf-rfid/helpers/encoder-hid.cpp b/applications/lf-rfid/helpers/encoder-hid.cpp index b0a6a34a..d63a52fc 100644 --- a/applications/lf-rfid/helpers/encoder-hid.cpp +++ b/applications/lf-rfid/helpers/encoder-hid.cpp @@ -2,12 +2,124 @@ #include void EncoderHID::init(const uint8_t* data, const uint8_t data_size) { - card_data = 0b1010000000000000000000000000000010011101111110011001001001010010; + furi_check(data_size == 3); + + card_data[0] = 0; + card_data[1] = 0; + card_data[2] = 0; + + uint32_t fc_cn = (data[0] << 16) | (data[1] << 8) | data[2]; + + // even parity sum calculation (high 12 bits of data) + uint8_t even_parity_sum = 0; + for(int8_t i = 12; i < 24; i++) { + if(((fc_cn >> i) & 1) == 1) { + even_parity_sum++; + } + } + + // odd parity sum calculation (low 12 bits of data) + uint8_t odd_parity_sum = 1; + for(int8_t i = 0; i < 12; i++) { + if(((fc_cn >> i) & 1) == 1) { + odd_parity_sum++; + } + } + + // 0x1D preamble + write_raw_bit(0, 0); + write_raw_bit(0, 1); + write_raw_bit(0, 2); + write_raw_bit(1, 3); + write_raw_bit(1, 4); + write_raw_bit(1, 5); + write_raw_bit(0, 6); + write_raw_bit(1, 7); + + // company / OEM code 1 + write_bit(0, 8); + write_bit(0, 10); + write_bit(0, 12); + write_bit(0, 14); + write_bit(0, 16); + write_bit(0, 18); + write_bit(1, 20); + + // card format / length 1 + write_bit(0, 22); + write_bit(0, 24); + write_bit(0, 26); + write_bit(0, 28); + write_bit(0, 30); + write_bit(0, 32); + write_bit(0, 34); + write_bit(0, 36); + write_bit(0, 38); + write_bit(0, 40); + write_bit(1, 42); + + // even parity bit + write_bit((even_parity_sum % 2), 44); + + // data + for(uint8_t i = 0; i < 24; i++) { + write_bit((fc_cn >> (23 - i)) & 1, 46 + (i * 2)); + } + + // odd parity bit + write_bit((odd_parity_sum % 2), 94); + card_data_index = 0; + bit_index = 0; +} + +void EncoderHID::write_bit(bool bit, uint8_t position) { + write_raw_bit(bit, position + 0); + write_raw_bit(!bit, position + 1); +} + +void EncoderHID::write_raw_bit(bool bit, uint8_t position) { + if(bit) { + card_data[position / 32] |= 1UL << (31 - (position % 32)); + } else { + card_data[position / 32] &= ~(1UL << (31 - (position % 32))); + } } void EncoderHID::get_next(bool* polarity, uint16_t* period, uint16_t* pulse) { - *period = 100; - *pulse = 50; + // hid 0 is 6 cycles by 8 clocks + const uint8_t hid_0_period = 8; + const uint8_t hid_0_count = 6; + // hid 1 is 5 cycles by 10 clocks + const uint8_t hid_1_period = 10; + const uint8_t hid_1_count = 5; + + bool bit = (card_data[card_data_index / 32] >> (31 - (card_data_index % 32))) & 1; + *polarity = true; + if(bit) { + *period = hid_1_period; + *pulse = hid_1_period / 2; + + bit_index++; + if(bit_index >= hid_1_count) { + bit_index = 0; + card_data_index++; + if(card_data_index >= (32 * card_data_max)) { + card_data_index = 0; + } + } + } else { + *period = hid_0_period; + *pulse = hid_0_period / 2; + + bit_index++; + if(bit_index >= hid_0_count) { + bit_index = 0; + card_data_index++; + if(card_data_index >= (32 * card_data_max)) { + card_data_index = 0; + } + } + } } diff --git a/applications/lf-rfid/helpers/encoder-hid.h b/applications/lf-rfid/helpers/encoder-hid.h index 3d8d3776..46c19224 100644 --- a/applications/lf-rfid/helpers/encoder-hid.h +++ b/applications/lf-rfid/helpers/encoder-hid.h @@ -14,6 +14,11 @@ public: void get_next(bool* polarity, uint16_t* period, uint16_t* pulse) final; private: - uint64_t card_data; + static const uint8_t card_data_max = 3; + uint32_t card_data[card_data_max]; uint8_t card_data_index; + uint8_t bit_index; + + void write_bit(bool bit, uint8_t position); + void write_raw_bit(bool bit, uint8_t position); }; \ No newline at end of file diff --git a/applications/lf-rfid/helpers/rfid-timer-emulator.cpp b/applications/lf-rfid/helpers/rfid-timer-emulator.cpp index 0d9aa789..947b8b5c 100644 --- a/applications/lf-rfid/helpers/rfid-timer-emulator.cpp +++ b/applications/lf-rfid/helpers/rfid-timer-emulator.cpp @@ -341,13 +341,14 @@ void RfidTimerEmulator::start(Type type) { if(encoders.count(type)) { current_encoder = encoders.find(type)->second; uint8_t em_data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2}; + uint8_t hid_data[3] = {0xED, 0x87, 0x70}; switch(type) { case Type::EM: current_encoder->init(em_data, 5); break; case Type::HID: - current_encoder->init(nullptr, 3); + current_encoder->init(hid_data, 3); break; case Type::Indala: current_encoder->init(nullptr, 5);