feat: add lf HIDProx read, t55xx write, emulate function (#267)

* feat: add lf HIDProx read, t55xx write, emulate function

code quaility:
- consistance: simulation -> emulation, label -> tag
- machine translated unreadable comments are made native

logic:
- newly added cli command includes: `lf hid prox read`, `lf hid prox write`, `lf hid prox econfig`
- machester demodulator is simplified
- various wiegand formats of HIDProx are supported
- goertzel algorithm is used in  HIDProx FSK demod
- lf read is refactored using stream/feed pattern to boost scan speed
- t55xx write is refactored to share same logic between em410x & HIDProx
- lf emulating is refactored to use PWM peripheral, allowing more card type to be added

closes: #212, #210

* chore: remove not implemented wiegand format comments

* fix: build ci

* fix: build ci

* fix: build ci

* fix: build ci
This commit is contained in:
TeCHiScy
2025-08-04 07:01:53 +02:00
committed by GitHub
parent cf00761902
commit 098e0a914b
60 changed files with 3364 additions and 1723 deletions
+9 -1
View File
@@ -18,6 +18,7 @@ SRC_FILES += \
$(PROJ_DIR)/bsp/bsp_delay.c \
$(PROJ_DIR)/bsp/bsp_time.c \
$(PROJ_DIR)/bsp/bsp_wdt.c \
$(PROJ_DIR)/rfid/byte_mirror.c \
$(PROJ_DIR)/rfid/crc_utils.c \
$(PROJ_DIR)/rfid/hex_utils.c \
$(PROJ_DIR)/rfid/mf1_crapto1.c \
@@ -30,6 +31,12 @@ SRC_FILES += \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_mf1.c \
$(PROJ_DIR)/rfid/nfctag/hf/nfc_mf0_ntag.c \
$(PROJ_DIR)/rfid/nfctag/lf/lf_tag_em.c \
$(PROJ_DIR)/rfid/nfctag/lf/utils/fskdemod.c \
$(PROJ_DIR)/rfid/nfctag/lf/utils/circular_buffer.c \
$(PROJ_DIR)/rfid/nfctag/lf/utils/manchester.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/em410x.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/hidprox.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/wiegand.c \
$(PROJ_DIR)/utils/dataframe.c \
$(PROJ_DIR)/utils/delayed_reset.c \
$(PROJ_DIR)/utils/fds_util.c \
@@ -174,6 +181,7 @@ INC_FOLDERS += \
${PROJ_DIR}/rfid/nfctag/ \
${PROJ_DIR}/rfid/nfctag/hf \
${PROJ_DIR}/rfid/nfctag/lf \
${PROJ_DIR}/rfid/nfctag/lf/utils \
$(SDK_ROOT)/components/nfc/ndef/generic/message \
$(SDK_ROOT)/components/nfc/t2t_lib \
$(SDK_ROOT)/components/nfc/t4t_parser/hl_detection_procedure \
@@ -329,12 +337,12 @@ ifeq (${CURRENT_DEVICE_TYPE}, ${CHAMELEON_ULTRA})
SRC_FILES +=\
$(PROJ_DIR)/rfid/reader/hf/mf1_toolbox.c \
$(PROJ_DIR)/rfid/reader/hf/rc522.c \
$(PROJ_DIR)/rfid/reader/lf/data_utils.c \
$(PROJ_DIR)/rfid/reader/lf/lf_125khz_radio.c \
$(PROJ_DIR)/rfid/reader/lf/lf_em410x_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_reader_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_reader_main.c \
$(PROJ_DIR)/rfid/reader/lf/lf_t55xx_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_hidprox_data.c \
INC_FOLDERS +=\
${PROJ_DIR}/rfid/reader/ \
+61 -11
View File
@@ -5,7 +5,6 @@
#include "rfid_main.h"
#include "ble_main.h"
#include "syssleep.h"
#include "tag_emulation.h"
#include "hex_utils.h"
#include "data_cmd.h"
#include "app_cmd.h"
@@ -603,17 +602,32 @@ static data_frame_tx_t *cmd_processor_mf1_manipulate_value_block(uint16_t cmd, u
}
static data_frame_tx_t *cmd_processor_em410x_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t id_buffer[5] = { 0x00 };
status = PcdScanEM410X(id_buffer);
uint8_t card_buffer[16] = { 0x00 };
status = scan_em410x(card_buffer);
if (status != STATUS_LF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}
return data_frame_make(cmd, STATUS_LF_TAG_OK, sizeof(id_buffer), id_buffer);
return data_frame_make(cmd, STATUS_LF_TAG_OK, sizeof(card_buffer), card_buffer);
}
static data_frame_tx_t *cmd_processor_em410x_write_to_t55XX(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
static data_frame_tx_t *cmd_processor_em410x_write_to_t55xx(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
typedef struct {
uint8_t id[5];
uint8_t new_key[4];
uint8_t old_keys[4]; // we can have more than one... struct just to compute offsets with min 1 key
} PACKED payload_t;
payload_t *payload = (payload_t *)data;
if (length < sizeof(payload_t) || (length - offsetof(payload_t, old_keys)) % sizeof(payload->old_keys) != 0) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
status = write_em410x_to_t55xx(payload->id, payload->new_key, payload->old_keys, (length - offsetof(payload_t, old_keys)) / sizeof(payload->old_keys));
return data_frame_make(cmd, status, 0, NULL);
}
static data_frame_tx_t *cmd_processor_hidprox_write_to_t55xx(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
typedef struct {
uint8_t id[13];
uint8_t old_key[4];
uint8_t new_keys[4]; // we can have more than one... struct just to compute offsets with min 1 key
} PACKED payload_t;
@@ -622,10 +636,24 @@ static data_frame_tx_t *cmd_processor_em410x_write_to_t55XX(uint16_t cmd, uint16
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
status = PcdWriteT55XX(payload->id, payload->old_key, payload->new_keys, (length - offsetof(payload_t, new_keys)) / sizeof(payload->new_keys));
uint8_t format = payload->id[0];
uint32_t fc = bytes_to_num(payload->id+1, 4);
uint64_t cn = payload->id[5];
cn = (cn << 32) | (bytes_to_num(payload->id+6, 4));
uint32_t il = payload->id[10];
uint32_t oem = bytes_to_num(payload->id+11, 2);
status = write_hidprox_to_t55xx(format, fc, cn, il, oem, payload->old_key, payload->new_keys, (length - offsetof(payload_t, new_keys)) / sizeof(payload->new_keys));
return data_frame_make(cmd, status, 0, NULL);
}
static data_frame_tx_t *cmd_processor_hidprox_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
uint8_t card_data[16] = { 0x00 };
status = scan_hidprox(card_data, data[0]);
if (status != STATUS_LF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}
return data_frame_make(cmd, STATUS_LF_TAG_OK, sizeof(card_data), card_data);
}
#endif
@@ -767,12 +795,30 @@ static data_frame_tx_t *cmd_processor_em410x_get_emu_id(uint16_t cmd, uint16_t s
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(tag_emulation_get_slot(), &tag_types);
if (tag_types.tag_lf != TAG_TYPE_EM410X) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, data); // no data in slot, don't send garbage
return data_frame_make(cmd, STATUS_PAR_ERR, 0, data); // no data in slot, don't send garbage
}
tag_data_buffer_t *buffer = get_buffer_by_tag_type(TAG_TYPE_EM410X);
uint8_t responseData[LF_EM410X_TAG_ID_SIZE];
memcpy(responseData, buffer->buffer, LF_EM410X_TAG_ID_SIZE);
return data_frame_make(cmd, STATUS_SUCCESS, LF_EM410X_TAG_ID_SIZE, responseData);
return data_frame_make(cmd, STATUS_SUCCESS, LF_EM410X_TAG_ID_SIZE, buffer->buffer);
}
static data_frame_tx_t *cmd_processor_hidprox_set_emu_id(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
if (length != LF_HIDPROX_TAG_ID_SIZE) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL);
}
tag_data_buffer_t *buffer = get_buffer_by_tag_type(TAG_TYPE_HID_PROX);
memcpy(buffer->buffer, data, LF_HIDPROX_TAG_ID_SIZE);
tag_emulation_load_by_buffer(TAG_TYPE_HID_PROX, false);
return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL);
}
static data_frame_tx_t *cmd_processor_hidprox_get_emu_id(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
tag_slot_specific_type_t tag_types;
tag_emulation_get_specific_types_by_slot(tag_emulation_get_slot(), &tag_types);
if (tag_types.tag_lf != TAG_TYPE_HID_PROX) {
return data_frame_make(cmd, STATUS_PAR_ERR, 0, data); // no data in slot, don't send garbage
}
tag_data_buffer_t *buffer = get_buffer_by_tag_type(TAG_TYPE_HID_PROX);
return data_frame_make(cmd, STATUS_SUCCESS, LF_HIDPROX_TAG_ID_SIZE, buffer->buffer);
}
static nfc_tag_14a_coll_res_reference_t *get_coll_res_data(bool write) {
@@ -1438,7 +1484,9 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_MF1_CHECK_KEYS_ON_BLOCK, before_hf_reader_run, cmd_processor_mf1_check_keys_on_block, after_hf_reader_run },
{ DATA_CMD_EM410X_SCAN, before_reader_run, cmd_processor_em410x_scan, NULL },
{ DATA_CMD_EM410X_WRITE_TO_T55XX, before_reader_run, cmd_processor_em410x_write_to_t55XX, NULL },
{ DATA_CMD_EM410X_WRITE_TO_T55XX, before_reader_run, cmd_processor_em410x_write_to_t55xx, NULL },
{ DATA_CMD_HIDPROX_SCAN, before_reader_run, cmd_processor_hidprox_scan, NULL },
{ DATA_CMD_HIDPROX_WRITE_TO_T55XX, before_reader_run, cmd_processor_hidprox_write_to_t55xx, NULL },
#endif
@@ -1476,6 +1524,8 @@ static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_MF0_NTAG_SET_WRITE_MODE, NULL, cmd_processor_mf0_ntag_set_write_mode, NULL },
{ DATA_CMD_EM410X_SET_EMU_ID, NULL, cmd_processor_em410x_set_emu_id, NULL },
{ DATA_CMD_EM410X_GET_EMU_ID, NULL, cmd_processor_em410x_get_emu_id, NULL },
{ DATA_CMD_HIDPROX_SET_EMU_ID, NULL, cmd_processor_hidprox_set_emu_id, NULL },
{ DATA_CMD_HIDPROX_GET_EMU_ID, NULL, cmd_processor_hidprox_get_emu_id, NULL },
};
data_frame_tx_t *cmd_processor_get_device_capabilities(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
+4 -4
View File
@@ -363,7 +363,7 @@ static void system_off_enter(void) {
// Set the reason for Reset. After restarting, you need to get this reason to avoid misjudgment from the source of wake up.
sd_power_gpregret_clr(1, GPREGRET_CLEAR_VALUE_DEFAULT);
sd_power_gpregret_set(1, RESET_ON_LF_FIELD_EXISTS_Msk);
// Trigger the RESET awakening system, restart the simulation process
// Trigger the RESET awakening system, restart the emulation process
nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_RESET);
return;
};
@@ -453,7 +453,7 @@ static void check_wakeup_src(void) {
}
}
// It is currently the wake -up system of the simulation card event, we can make the strong lights on the field first
// It is currently the wake-up system of the emulation card event, we can make the strong lights on the field first
TAG_FIELD_LED_ON();
uint8_t animation_config = settings_get_animation_config();
@@ -611,7 +611,7 @@ static void btn_fn_copy_ic_uid(void) {
switch (tag_types.tag_lf) {
case TAG_TYPE_EM410X:
status = PcdScanEM410X(id_buffer);
status = scan_em410x(id_buffer);
if (status == STATUS_LF_TAG_OK) {
tag_data_buffer_t *buffer = get_buffer_by_tag_type(TAG_TYPE_EM410X);
@@ -853,7 +853,7 @@ int main(void) {
on_data_frame_complete(on_data_frame_received);
check_wakeup_src(); // Detect wake-up source and decide BLE broadcast and subsequent hibernation action according to the wake-up source
tag_mode_enter(); // Enter card simulation mode by default
tag_mode_enter(); // Enter card emulation mode by default
// usbd event listener
APP_ERROR_CHECK(app_usbd_power_events_enable());
+2
View File
@@ -20,6 +20,8 @@
/////////////////////////////////////////////////////////////////////
#define STATUS_LF_TAG_OK (0x40) // Some of the low -frequency cards are successful!
#define STATUS_EM410X_TAG_NO_FOUND (0x41) // Can't search for valid EM410X tags
#define STATUS_LF_TAG_NO_FOUND (0x42) // Can't search for valid LF tag
#define STATUS_HIDPROX_TAG_NO_FOUND (0x43) // Can't search for valid HIDProx tags
/////////////////////////////////////////////////////////////////////
+5 -9
View File
@@ -1,20 +1,16 @@
#include "bsp_delay.h"
#include "bsp_time.h"
#include "nrf_delay.h"
//Initialized delay function
void bsp_delay_init(void) {
}
//Delay NMS
//Pay attention to the range of NMS
// Delay NMS
// Pay attention to the range of NMS
void bsp_delay_ms(uint16_t nms) {
nrf_delay_us(nms * 1000);
}
//Delay NUS
//NUS is the number of US numbers to be delayed.
// Delay NUS
// NUS is the number of US numbers to be delayed.
void bsp_delay_us(uint32_t nus) {
nrf_delay_us(nus);
}
-1
View File
@@ -7,7 +7,6 @@
extern "C" {
#endif
void bsp_delay_init(void);
void bsp_delay_ms(uint16_t nms);
void bsp_delay_us(uint32_t nus);
+4
View File
@@ -84,6 +84,8 @@
//
#define DATA_CMD_EM410X_SCAN (3000)
#define DATA_CMD_EM410X_WRITE_TO_T55XX (3001)
#define DATA_CMD_HIDPROX_SCAN (3002)
#define DATA_CMD_HIDPROX_WRITE_TO_T55XX (3003)
//
// ******************************************************************
@@ -140,5 +142,7 @@
// ******************************************************************
#define DATA_CMD_EM410X_SET_EMU_ID (5000)
#define DATA_CMD_EM410X_GET_EMU_ID (5001)
#define DATA_CMD_HIDPROX_SET_EMU_ID (5002)
#define DATA_CMD_HIDPROX_GET_EMU_ID (5003)
#endif
@@ -0,0 +1,37 @@
#include "byte_mirror.h"
// Byte mirror
const uint8_t byte_mirror[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
@@ -0,0 +1,17 @@
#ifndef __BYTE_MIRROR_H__
#define __BYTE_MIRROR_H__
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const uint8_t byte_mirror[256];
#ifdef __cplusplus
}
#endif
#endif
+13 -15
View File
@@ -1,14 +1,13 @@
#include "hex_utils.h"
/**
* @brief : Convert the large number to the hex byte array
* @param :n : The value of the conversion
* @param :len : The byte length of the value after the conversion is stored
* @param :dest : Caps that store conversion results
* @retval : none
*
*/
* @brief Convert the large number to the hex byte array
* @param n : The value of the conversion
* @param len : The byte length of the value after the conversion is stored
* @param dest : Caps that store conversion results
* @retval none
*
*/
void num_to_bytes(uint64_t n, uint8_t len, uint8_t *dest) {
while (len--) {
dest[len] = (uint8_t)n;
@@ -17,12 +16,12 @@ void num_to_bytes(uint64_t n, uint8_t len, uint8_t *dest) {
}
/**
* @brief : Convert byte array to large number
* @param :len : The byte length of the buffer of the value of the value
* @param :src : Byte buffer stored in the numerical
* @retval : Converting result
*
*/
* @brief Convert byte array to large number
* @param len : The byte length of the buffer of the value of the value
* @param src : Byte buffer stored in the numerical
* @retval Converting result
*
*/
uint64_t bytes_to_num(uint8_t *src, uint8_t len) {
uint64_t num = 0;
while (len--) {
@@ -31,4 +30,3 @@ uint64_t bytes_to_num(uint8_t *src, uint8_t len) {
}
return num;
}
+2 -3
View File
@@ -1,9 +1,8 @@
#ifndef __HEX_UTILS_H
#define __HEX_UTILS_H
#ifndef __HEX_UTILS_H__
#define __HEX_UTILS_H__
#include <stdint.h>
// num & bytes
void num_to_bytes(uint64_t n, uint8_t len, uint8_t *dest);
uint64_t bytes_to_num(uint8_t *src, uint8_t len);
@@ -11,6 +11,7 @@ NRF_LOG_MODULE_REGISTER();
#include "hex_utils.h"
#include "crc_utils.h"
#include "nfc_mf1.h"
#include "byte_mirror.h"
#include "rfid_main.h"
#include "syssleep.h"
@@ -46,42 +47,6 @@ nfc_tag_14a_handler_t m_tag_handler = {
.get_coll_res = NULL, // Obtain packaging of anti -conflict resources of labels
};
// Byte mirror
const uint8_t ByteMirror[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
// RATS FSDI length check table
const uint16_t ats_fsdi_table[] = {
// 0 - 8
@@ -90,9 +55,8 @@ const uint16_t ats_fsdi_table[] = {
256, 256, 256, 256, 256, 256, 256,
};
// Whether it is responding to
static volatile bool m_is_responded = false;
static volatile bool m_is_responded = false;
// Receiving buffer
static uint8_t m_nfc_rx_buffer[MAX_NFC_RX_BUFFER_SIZE] = { 0x00 };
static uint8_t m_nfc_tx_buffer[MAX_NFC_TX_BUFFER_SIZE] = { 0x00 };
@@ -184,16 +148,16 @@ uint8_t nfc_tag_14a_wrap_frame(const uint8_t *pbtTx, const size_t szTxBits, cons
for (uiBitPos = 0; uiBitPos < 8; uiBitPos++) {
// Copy as much data that fits in the frame byte
btData = ByteMirror[pbtTx[uiDataPos]];
btData = byte_mirror[pbtTx[uiDataPos]];
btFrame |= (btData >> uiBitPos);
// Save this frame byte
*pbtFrame = ByteMirror[btFrame];
*pbtFrame = byte_mirror[btFrame];
// Set the remaining bits of the date in the new frame byte and append the parity bit
btFrame = (btData << (8 - uiBitPos));
btFrame |= ((pbtTxPar[uiDataPos] & 0x01) << (7 - uiBitPos));
// Backup the frame bits we have so far
pbtFrame++;
*pbtFrame = ByteMirror[btFrame];
*pbtFrame = byte_mirror[btFrame];
// Increase the data (without parity bit) position
uiDataPos++;
// Test if we are done
@@ -242,11 +206,11 @@ uint8_t nfc_tag_14a_unwrap_frame(const uint8_t *pbtFrame, const size_t szFrameBi
// This process is the reverse of WrapFrame(), look there for more info
while (1) {
for (uiBitPos = 0; uiBitPos < 8; uiBitPos++) {
btFrame = ByteMirror[pbtFramePos[uiDataPos]];
btFrame = byte_mirror[pbtFramePos[uiDataPos]];
btData = (btFrame << uiBitPos);
btFrame = ByteMirror[pbtFramePos[uiDataPos + 1]];
btFrame = byte_mirror[pbtFramePos[uiDataPos + 1]];
btData |= (btFrame >> (8 - uiBitPos));
pbtRx[uiDataPos] = ByteMirror[btData];
pbtRx[uiDataPos] = byte_mirror[btData];
if (pbtRxPar != NULL)
pbtRxPar[uiDataPos] = ((btFrame >> (7 - uiBitPos)) & 0x01);
// Increase the data (without parity bit) position
@@ -130,7 +130,7 @@ static nfc_tag_mf0_ntag_information_t *m_tag_information = NULL;
static nfc_tag_14a_coll_res_reference_t m_shadow_coll_res;
//Define and use MF0/NTAG special communication buffer
static nfc_tag_mf0_ntag_tx_buffer_t m_tag_tx_buffer;
// Save the specific type of MF0/NTAG currently being simulated
// Save the specific type of MF0/NTAG currently being emulated
static tag_specific_type_t m_tag_type;
static bool m_tag_authenticated = false;
static bool m_did_first_read = false;
@@ -1086,7 +1086,7 @@ int nfc_tag_mf0_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *bu
if (buffer->length >= info_size) {
// Convert the data buffer to MF0/NTAG structure type
m_tag_information = (nfc_tag_mf0_ntag_information_t *)buffer->buffer;
// The specific type of MF0/NTAG tag that is simulated by the cache
// The specific type of MF0/NTAG tag that is emulated by the cache
m_tag_type = type;
// Register 14A communication management interface
nfc_tag_14a_handler_t handler_for_14a = {
@@ -188,7 +188,7 @@ static nfc_tag_14a_coll_res_reference_t m_shadow_coll_res;
static nfc_tag_mf1_trailer_info_t *m_tag_trailer_info = NULL;
// Define and use MF1 special communication buffer
static nfc_tag_mf1_tx_buffer_t m_tag_tx_buffer;
//Save the specific type of MF1 currently being simulated
//Save the specific type of MF1 currently being emulated
static tag_specific_type_t m_tag_type;
// Fast simulate is enable, we use internal crypto1 instance from 'mf1_crypto1.c'
@@ -500,7 +500,7 @@ void nfc_tag_mf1_state_handler(uint8_t *p_data, uint16_t szDataBits) {
BlockEnd = BlockStart + 4 - 1;
}
// The type of current simulation card is not enough to support the access of the card reader
// The type of current emulation card is not enough to support the access of the card reader
if (check_block_max_overflow(BlockAuth)) {
break;
}
@@ -805,7 +805,7 @@ void nfc_tag_mf1_state_handler(uint8_t *p_data, uint16_t szDataBits) {
BlockEnd = BlockStart + 4 - 1;
}
// The type of current simulation card is not enough to support the access of the card reader
// The type of current emulation card is not enough to support the access of the card reader
if (check_block_max_overflow(BlockAuth)) {
break;
}
@@ -1016,7 +1016,7 @@ void nfc_tag_mf1_state_handler(uint8_t *p_data, uint16_t szDataBits) {
* @brief Provide the necessary anti -conflict resources for the MiFare label (only pointer provides pointers)
*/
nfc_tag_14a_coll_res_reference_t *get_mifare_coll_res() {
//According to the current interoperability configuration, selectively return the configuration data to selectively, assuming that the data interoperability is turned on, then we also need to ensure that the current simulation card is 4BYTE
//According to the current interoperability configuration, selectively return the configuration data to selectively, assuming that the data interoperability is turned on, then we also need to ensure that the current emulation card is 4BYTE
if (m_tag_information->config.use_mf1_coll_res && m_tag_information->res_coll.size == NFC_TAG_14A_UID_SINGLE_SIZE) {
// Manufacturer information obtained by the data area
nfc_tag_mf1_factory_info_t *block0_factory_info = (nfc_tag_mf1_factory_info_t *)m_tag_information->memory[0];
@@ -1102,7 +1102,7 @@ int nfc_tag_mf1_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer)
if (buffer->length >= info_size) {
//Convert the data buffer to MF1 structure type
m_tag_information = (nfc_tag_mf1_information_t *)buffer->buffer;
// The specific type of MF1 that is simulated by the cache
// The specific type of MF1 that is emulated by the cache
m_tag_type = type;
// Register 14A communication management interface
nfc_tag_14a_handler_t handler_for_14a = {
File diff suppressed because it is too large Load Diff
@@ -1,25 +1,17 @@
#ifndef __LF_TAG_H
#define __LF_TAG_H
#pragma once
#include <stdbool.h>
#include "rfid_main.h"
#include "tag_emulation.h"
/**
* Low -frequency analog card adjustment Manchester signal
* The definition of the packaging tool macro only needs to be modulated 0 and 1
*/
#define LF_125KHZ_EM410X_BIT_SIZE 64
#define LF_125KHZ_BROADCAST_MAX 10 // 32.768ms once, about 31 times in one second
#define LF_125KHZ_EM410X_BIT_CLOCK 256
#define LF_EM410X_TAG_ID_SIZE 5
#define LF_EM410X_TAG_ID_SIZE 5
#define LF_HIDPROX_TAG_ID_SIZE 13
void lf_tag_125khz_sense_switch(bool enable);
int lf_tag_em410x_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer);
int lf_tag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer);
int lf_tag_em410x_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer);
bool lf_tag_em410x_data_factory(uint8_t slot, tag_specific_type_t tag_type);
int lf_tag_hidprox_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer);
bool lf_tag_hidprox_data_factory(uint8_t slot, tag_specific_type_t tag_type);
bool lf_is_field_exists(void);
#endif
@@ -0,0 +1,280 @@
#include "em410x.h"
#include <stdlib.h>
#include <string.h>
#include "em410x.h"
#include "nordic_common.h"
#include "nrf_pwm.h"
#include "parity.h"
#include "protocols.h"
#include "t55xx.h"
#include "tag_base_type.h"
#include "utils/manchester.h"
#define EM_BITS_PER_ROW_COUNT (EM_COLUMN_COUNT + 1)
#define EM_RAW_SIZE (64)
#define EM_DATA_SIZE (5)
#define EM_ROW_COUNT (10)
#define EM_COLUMN_COUNT (4)
#define EM_HEADER (0x1ff) // 9 bits of 1
#define EM_T55XX_BLOCK_COUNT (3)
#define EM_READ_TIME1_BASE (0x40)
#define EM_READ_TIME2_BASE (0x60)
#define EM_READ_TIME3_BASE (0x80)
#define EM_READ_JITTER_TIME_BASE (0x10)
#define NRF_LOG_MODULE_NAME em4100
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
NRF_LOG_MODULE_REGISTER();
static nrf_pwm_values_wave_form_t m_em410x_pwm_seq_vals[EM_RAW_SIZE] = {};
nrf_pwm_sequence_t const m_em410x_pwm_seq = {
.values.p_wave_form = m_em410x_pwm_seq_vals,
.length = NRF_PWM_VALUES_LENGTH(m_em410x_pwm_seq_vals),
.repeats = 0,
.end_delay = 0,
};
const protocol *em410x_protocols[] = {
&em410x_64,
&em410x_32,
&em410x_16,
};
size_t em410x_protocols_size = ARRAY_SIZE(em410x_protocols);
typedef struct {
uint8_t data[EM_DATA_SIZE];
uint64_t raw;
uint8_t raw_length;
manchester *modem;
} em410x_codec;
uint64_t em410x_raw_data(uint8_t *uid) {
uint64_t raw = EM_HEADER;
uint8_t pc = 0x00; // column parity
// 10 rows, each row is 4 bits data + 1 bit parity
for (int8_t i = 0; i < EM_ROW_COUNT; i++) {
uint8_t data;
if (i % 2) {
data = uid[i >> 1] & 0x0f;
} else {
data = (uid[i >> 1] >> EM_COLUMN_COUNT) & 0x0f;
}
pc ^= data;
raw = (raw << EM_COLUMN_COUNT) | data;
raw <<= 1;
if (!oddparity8(data)) {
raw |= 0x01; // row parity bit
}
}
raw = (raw << EM_COLUMN_COUNT) | pc; // column parity
raw <<= 1; // stop bit
return raw;
}
bool em410x_get_time(uint16_t divisor, uint8_t interval, uint8_t base) {
return interval >= (base - EM_READ_JITTER_TIME_BASE) / divisor &&
interval <= (base + EM_READ_JITTER_TIME_BASE) / divisor;
}
uint8_t em410x_period(uint16_t divisor, uint8_t interval) {
if (em410x_get_time(divisor, interval, EM_READ_TIME1_BASE)) {
return 0;
}
if (em410x_get_time(divisor, interval, EM_READ_TIME2_BASE)) {
return 1;
}
if (em410x_get_time(divisor, interval, EM_READ_TIME3_BASE)) {
return 2;
}
return 3;
}
uint8_t em410x_64_period(uint8_t interval) {
return em410x_period(1, interval); // clock_per_bit = 64, divisor = 1
}
uint8_t em410x_32_period(uint8_t interval) {
return em410x_period(2, interval); // clock_per_bit = 32, divisor = 2
}
uint8_t em410x_16_period(uint8_t interval) {
return em410x_period(4, interval); // clock_per_bit = 16, divisor = 4
}
em410x_codec *em410x_64_alloc(void) {
em410x_codec *codec = malloc(sizeof(em410x_codec));
codec->modem = malloc(sizeof(manchester));
codec->modem->rp = em410x_64_period;
return codec;
};
em410x_codec *em410x_32_alloc(void) {
em410x_codec *codec = malloc(sizeof(em410x_codec));
codec->modem = malloc(sizeof(manchester));
codec->modem->rp = em410x_32_period;
return codec;
};
em410x_codec *em410x_16_alloc(void) {
em410x_codec *codec = malloc(sizeof(em410x_codec));
codec->modem = malloc(sizeof(manchester));
codec->modem->rp = em410x_16_period;
return codec;
};
void em410x_free(em410x_codec *d) {
if (d->modem) {
free(d->modem);
d->modem = NULL;
}
free(d);
};
uint8_t *em410x_get_data(em410x_codec *d) { return d->data; };
void em410x_decoder_start(em410x_codec *d, uint8_t format) {
memset(d->data, 0, EM_DATA_SIZE);
d->raw = 0;
d->raw_length = 0;
manchester_reset(d->modem);
};
bool em410x_decode_feed(em410x_codec *d, bool bit) {
d->raw <<= 1;
d->raw_length++;
if (bit) {
d->raw |= 0x01;
}
if (d->raw_length < EM_RAW_SIZE) {
return false;
}
// check header
uint8_t v = (d->raw >> (EM_RAW_SIZE - 8)) & 0xff;
if (v != 0xff) {
return false;
}
v = (d->raw >> (EM_RAW_SIZE - 9)) & 0xff;
if (v != 0xff) {
return false;
}
// check stop bit
if (d->raw & 0x01) {
return false;
}
uint8_t pc = 0;
for (int i = 0; i < EM_ROW_COUNT + 1; i++) {
uint8_t row = d->raw >> (EM_RAW_SIZE - 9 - (i + 1) * EM_BITS_PER_ROW_COUNT) & 0x1f;
uint8_t data = (row >> 1) & 0x0f;
pc ^= data;
if (i == 10) {
break;
}
if (!oddparity8(row)) { // row parity
return false;
}
if (i % 2) {
d->data[i >> 1] |= data;
} else {
d->data[i >> 1] = data << 4;
}
}
return pc == 0x00; // column parity
}
bool em410x_decoder_feed(em410x_codec *d, uint16_t interval) {
bool bits[2] = {0};
int8_t bitlen = 0;
manchester_feed(d->modem, (uint8_t)interval, bits, &bitlen);
if (bitlen == -1) {
d->raw = 0;
d->raw_length = 0;
return false;
}
for (int i = 0; i < bitlen; i++) {
if (em410x_decode_feed(d, bits[i])) {
return true;
}
}
return false;
};
const nrf_pwm_sequence_t *em410x_modulator(em410x_codec *d, uint8_t *buf) {
uint64_t lo = em410x_raw_data(buf);
for (int i = 0; i < EM_RAW_SIZE; i++) {
uint16_t msb = 0x00;
if (IS_SET(lo, EM_RAW_SIZE - i - 1)) {
msb = (1 << 15);
}
m_em410x_pwm_seq_vals[i].channel_0 = msb | 32;
m_em410x_pwm_seq_vals[i].counter_top = 64;
}
return &m_em410x_pwm_seq;
};
// EM-Micro, EM410x/64 (std)
const protocol em410x_64 = {
.tag_type = TAG_TYPE_EM410X_64,
.data_size = EM_DATA_SIZE,
.alloc = (codec_alloc)em410x_64_alloc,
.free = (codec_free)em410x_free,
.get_data = (codec_get_data)em410x_get_data,
.modulator = (modulator)em410x_modulator,
.decoder =
{
.start = (decoder_start)em410x_decoder_start,
.feed = (decoder_feed)em410x_decoder_feed,
},
};
// EM-Micro, EM410x/32
const protocol em410x_32 = {
.tag_type = TAG_TYPE_EM410X_32,
.data_size = EM_DATA_SIZE,
.alloc = (codec_alloc)em410x_32_alloc,
.free = (codec_free)em410x_free,
.get_data = (codec_get_data)em410x_get_data,
.modulator = (modulator)em410x_modulator,
.decoder =
{
.start = (decoder_start)em410x_decoder_start,
.feed = (decoder_feed)em410x_decoder_feed,
},
};
// EM-Micro, EM410x/16
const protocol em410x_16 = {
.tag_type = TAG_TYPE_EM410X_16,
.data_size = EM_DATA_SIZE,
.alloc = (codec_alloc)em410x_16_alloc,
.free = (codec_free)em410x_free,
.get_data = (codec_get_data)em410x_get_data,
.modulator = (modulator)em410x_modulator,
.decoder =
{
.start = (decoder_start)em410x_decoder_start,
.feed = (decoder_feed)em410x_decoder_feed,
},
};
// Encode EM410X card number to T55xx blocks.
uint8_t em410x_t55xx_writer(uint8_t *uid, uint32_t *blks) {
uint64_t raw = em410x_raw_data(uid);
blks[0] = T5577_EM410X_64_CONFIG;
blks[1] = raw >> 32;
blks[2] = raw & 0xffffffff;
return EM_T55XX_BLOCK_COUNT;
}
@@ -0,0 +1,12 @@
#pragma once
#include "protocols.h"
extern const protocol em410x_64;
extern const protocol em410x_32;
extern const protocol em410x_16;
extern const protocol* em410x_protocols[];
extern size_t em410x_protocols_size;
uint8_t em410x_t55xx_writer(uint8_t* uid, uint32_t* blks);
@@ -0,0 +1,239 @@
#include "hidprox.h"
#include <stdlib.h>
#include <string.h>
#include "hex_utils.h"
#include "nordic_common.h"
#include "parity.h"
#include "protocols.h"
#include "t55xx.h"
#include "tag_base_type.h"
#include "wiegand.h"
#define HIDPROX_SOF (0x1d)
#define HIDPROX_T55XX_BLOCK_COUNT (4)
#define DEMOD_BUFFER_SIZE (32)
#define HIDPROX_RAW_SIZE (96)
#define LF_FSK2a_PWM_LO_FREQ_LOOP (5)
#define LF_FSK2a_PWM_LO_FREQ_TOP_VALUE (10)
#define LF_FSK2a_PWM_HI_FREQ_LOOP (6)
#define LF_FSK2a_PWM_HI_FREQ_TOP_VALUE (8)
static nrf_pwm_values_wave_form_t m_hidprox_pwm_seq_vals[HIDPROX_RAW_SIZE * 6] = {};
nrf_pwm_sequence_t m_hidprox_pwm_seq = {
.values.p_wave_form = m_hidprox_pwm_seq_vals,
.length = NRF_PWM_VALUES_LENGTH(m_hidprox_pwm_seq_vals),
.repeats = 0,
.end_delay = 0,
};
void decoder_reset(hidprox_codec *d) {
d->sof = 0;
d->state = STATE_SOF;
d->raw = 0;
d->raw_length = 0;
d->bit = false;
}
void hidprox_decoder_start(hidprox_codec *d, uint8_t format_hint) {
memset(d->data, 0, HIDPROX_DATA_SIZE);
decoder_reset(d);
d->format_hint = format_hint;
}
hidprox_codec *hidprox_codec_alloc(void) {
hidprox_codec *d = malloc(sizeof(hidprox_codec));
d->card = NULL;
d->modem = fsk_alloc();
return d;
}
void hidprox_codec_free(hidprox_codec *d) {
if (d->modem) {
fsk_free(d->modem);
d->modem = NULL;
}
if (d->card) {
free(d->card);
d->card = NULL;
}
free(d);
}
// ref: https://github.com/RfidResearchGroup/proxmark3/blob/810eaeac250f35eca8819aa9c23cb57c5276b3e6/client/src/wiegand_formatutils.c#L131
static uint8_t hidprox_codec_get_length(hidprox_codec *d) {
//! TODO direct XOR check
if (!(d->raw >> 37) && 0x01) {
return 37;
}
uint16_t bits = (d->raw >> 26) & 0x7ff;
uint8_t length = 25;
while (bits) {
bits >>= 1;
length++;
}
return length;
}
uint8_t *hidprox_get_data(hidprox_codec *d) {
if (d->card == NULL) {
return d->data;
}
// total 13 bytes
d->data[0] = d->card->format;
num_to_bytes(d->card->facility_code, 4, d->data + 1); // 4 bytes
num_to_bytes(d->card->card_number, 5, d->data + 5); // 5 bytes
num_to_bytes(d->card->issue_level, 1, d->data + 10); // 1 bytes
num_to_bytes(d->card->oem, 2, d->data + 11); // 2 bytes
return d->data;
};
bool hidprox_decode_feed(hidprox_codec *d, bool bit) {
if (d->state == STATE_SOF) {
d->sof <<= 1;
if (bit) {
SET_BIT(d->sof, 0);
}
if (d->sof == HIDPROX_SOF) { // found start of frame
d->state = STATE_DATA_LO;
}
return false;
}
if (d->state == STATE_DATA_LO) {
d->bit = bit;
d->state = STATE_DATA_HI;
return false;
}
if (d->state == STATE_DATA_HI) {
if (bit == d->bit) { // invalid manchester bit
decoder_reset(d);
return false;
}
d->raw <<= 1;
d->raw_length++;
if (d->bit && !bit) {
SET_BIT(d->raw, 0);
}
if (d->raw_length < 44) {
d->state = STATE_DATA_LO;
return false;
}
d->state = STATE_DONE;
uint8_t length = hidprox_codec_get_length(d);
wiegand_card_t *card = unpack(d->format_hint, length, 0, d->raw);
if (card == NULL) {
decoder_reset(d);
return false;
}
d->card = card;
return true;
}
return false;
}
bool hidprox_decoder_feed(hidprox_codec *d, uint16_t val) {
bool bit = false;
if (!fsk_feed(d->modem, val, &bit)) {
return false;
}
return hidprox_decode_feed(d, bit);
}
void hidprox_raw_data(wiegand_card_t *card, uint32_t *hi, uint32_t *mid, uint32_t *bot) {
*hi = 0;
*mid = 0;
*bot = 0;
uint64_t data = pack(card);
if (data == 0) {
return;
}
*hi = HIDPROX_SOF;
for (uint8_t i = 0; i < 44; i++) {
uint32_t *blk;
if (i < 12) {
blk = hi;
} else if (i < 28) {
blk = mid;
} else {
blk = bot;
}
*blk <<= 2;
if ((data >> (43 - i)) & 0x01) {
*blk |= 0x02;
} else {
*blk |= 0x01;
}
}
}
// fsk2a modulator
const nrf_pwm_sequence_t *hidprox_modulator(hidprox_codec *d, uint8_t *buf) {
uint64_t cn = buf[5];
cn = (cn << 32) | (bytes_to_num(buf + 6, 4));
wiegand_card_t card = {
.facility_code = bytes_to_num(buf + 1, 4),
.card_number = cn,
.issue_level = buf[10],
.oem = bytes_to_num(buf + 11, 2),
.format = buf[0],
};
uint32_t hi, mid, bot;
hidprox_raw_data(&card, &hi, &mid, &bot);
int k = 0;
for (int i = 0; i < HIDPROX_RAW_SIZE; i++) {
bool bit = false;
if (i < 32) {
bit = (hi >> (31 - i)) & 1;
} else if (i < 64) {
bit = (mid >> (63 - i)) & 1;
} else {
bit = (bot >> (95 - i)) & 1;
}
if (!bit) {
for (int j = 0; j < LF_FSK2a_PWM_HI_FREQ_LOOP; j++) {
m_hidprox_pwm_seq_vals[k].channel_0 = LF_FSK2a_PWM_HI_FREQ_TOP_VALUE / 2;
m_hidprox_pwm_seq_vals[k].counter_top = LF_FSK2a_PWM_HI_FREQ_TOP_VALUE;
k++;
}
} else {
for (int j = 0; j < LF_FSK2a_PWM_LO_FREQ_LOOP; j++) {
m_hidprox_pwm_seq_vals[k].channel_0 = LF_FSK2a_PWM_LO_FREQ_TOP_VALUE / 2;
m_hidprox_pwm_seq_vals[k].counter_top = LF_FSK2a_PWM_LO_FREQ_TOP_VALUE;
k++;
}
}
}
m_hidprox_pwm_seq.length = k * 4;
return &m_hidprox_pwm_seq;
};
const protocol hidprox = {
.tag_type = TAG_TYPE_HID_PROX,
.data_size = HIDPROX_DATA_SIZE,
.alloc = (codec_alloc)hidprox_codec_alloc,
.free = (codec_free)hidprox_codec_free,
.get_data = (codec_get_data)hidprox_get_data,
.modulator = (modulator)hidprox_modulator,
.decoder =
{
.start = (decoder_start)hidprox_decoder_start,
.feed = (decoder_feed)hidprox_decoder_feed,
},
};
uint8_t hidprox_t55xx_writer(wiegand_card_t *card, uint32_t *blks) {
blks[0] = T5577_HIDPROX_CONFIG;
hidprox_raw_data(card, &blks[1], &blks[2], &blks[3]);
return HIDPROX_T55XX_BLOCK_COUNT;
}
@@ -0,0 +1,33 @@
#pragma once
#include "protocols.h"
#include "utils/fskdemod.h"
#include "wiegand.h"
#define HIDPROX_DATA_SIZE (16)
typedef enum {
STATE_SOF,
STATE_DATA_LO,
STATE_DATA_HI,
STATE_DONE,
} hidprox_codec_state_t;
typedef struct {
uint8_t data[HIDPROX_DATA_SIZE];
bool bit;
uint8_t sof;
uint64_t raw;
uint8_t raw_length;
fsk_t *modem;
hidprox_codec_state_t state;
uint8_t format_hint;
wiegand_card_t *card;
} hidprox_codec;
extern const protocol hidprox;
uint8_t hidprox_t55xx_writer(wiegand_card_t *card, uint32_t *blks);

Some files were not shown because too many files have changed in this diff Show More