Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions firmware/application/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ SRC_FILES += \
$(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/ioprox.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/hidprox.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/ioprox.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/viking.c \
$(PROJ_DIR)/rfid/nfctag/lf/protocols/wiegand.c \
$(PROJ_DIR)/utils/dataframe.c \
Expand Down Expand Up @@ -341,13 +341,15 @@ ifeq (${CURRENT_DEVICE_TYPE}, ${CHAMELEON_ULTRA})
$(PROJ_DIR)/rfid/reader/hf/rc522.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_em4x05_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_gap.c \
$(PROJ_DIR)/rfid/reader/lf/lf_reader_generic.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_ioprox_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_hidprox_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_ioprox_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_viking_data.c \
$(PROJ_DIR)/rfid/reader/lf/lf_reader_generic.c \

INC_FOLDERS +=\
${PROJ_DIR}/rfid/reader/ \
Expand Down
120 changes: 120 additions & 0 deletions firmware/application/src/app_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
#include "settings.h"
#include "delayed_reset.h"
#include "netdata.h"
#if defined(PROJECT_CHAMELEON_ULTRA)
#include "bsp_wdt.h"
#include "lf_reader_generic.h"
#include "lf_em4x05_data.h"
#endif
#include "nfc_14a.h"


#define NRF_LOG_MODULE_NAME app_cmd
Expand Down Expand Up @@ -1729,6 +1735,117 @@ static data_frame_tx_t *cmd_processor_mf0_get_emulator_config(uint16_t cmd, uint
* (cmd -> processor) function map, the map struct is:
* cmd code before process cmd processor after process
*/
#if defined(PROJECT_CHAMELEON_ULTRA)
static data_frame_tx_t *cmd_processor_em4x05_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
em4x05_data_t tag = {0};
status = scan_em4x05(&tag);
if (status != STATUS_LF_TAG_OK) {
return data_frame_make(cmd, status, 0, NULL);
}
struct {
uint32_t config;
uint32_t uid;
uint32_t uid_hi;
uint8_t is_em4x69;
} PACKED payload;
payload.config = U32HTONL(tag.config);
payload.uid = U32HTONL(tag.uid);
payload.uid_hi = U32HTONL(tag.uid_hi);
payload.is_em4x69 = tag.is_em4x69 ? 1 : 0;
return data_frame_make(cmd, STATUS_LF_TAG_OK, sizeof(payload), (uint8_t *)&payload);
}

static data_frame_tx_t *cmd_processor_lf_sniff(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
/* Optional 2-byte big-endian timeout in ms from host (default 2000ms) */
uint32_t timeout_ms = 2000;
if (length >= 2) {
timeout_ms = ((uint32_t)data[0] << 8) | data[1];
if (timeout_ms == 0 || timeout_ms > 10000) timeout_ms = 2000;
}

static uint8_t sniff_buf[LF_SNIFF_MAX_SAMPLES];
size_t outlen = 0;
raw_read_to_buffer(sniff_buf, LF_SNIFF_MAX_SAMPLES, timeout_ms, &outlen);

if (outlen == 0) {
return data_frame_make(cmd, STATUS_LF_TAG_NO_FOUND, 0, NULL);
}
return data_frame_make(cmd, STATUS_LF_TAG_OK, (uint16_t)outlen, sniff_buf);
}
#define HF_SNIFF_BUF_SIZE 3800 /* leave room for USB framing */
#define HF_SNIFF_MAX_FRAMES 200

static uint8_t m_sniff_buf[HF_SNIFF_BUF_SIZE];
static uint16_t m_sniff_buf_len = 0;
static bool m_sniff_active = false;
static uint16_t m_sniff_cb_count = 0; /* debug: total callback invocations */

static void hf14a_sniff_frame_cb(const uint8_t *data, uint16_t szBits) {
m_sniff_cb_count++; /* count even if buffer full or inactive */
if (!m_sniff_active) return;
uint16_t szBytes = (szBits + 7) / 8;
/* Check space: 2 bytes header + data */
if (m_sniff_buf_len + 2 + szBytes > HF_SNIFF_BUF_SIZE) return;
/* Write bit count big-endian */
m_sniff_buf[m_sniff_buf_len++] = (szBits >> 8) & 0xFF;
m_sniff_buf[m_sniff_buf_len++] = szBits & 0xFF;
/* Write frame bytes */
memcpy(&m_sniff_buf[m_sniff_buf_len], data, szBytes);
m_sniff_buf_len += szBytes;
}

static data_frame_tx_t *cmd_processor_hf14a_sniff(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
/* Optional 2-byte big-endian timeout in ms (default 5000ms) */
uint32_t timeout_ms = 5000;
if (length >= 2) {
timeout_ms = ((uint32_t)data[0] << 8) | data[1];
if (timeout_ms == 0 || timeout_ms > 30000) timeout_ms = 5000;
}

/* Reload active slot data before sniffing.
* The NFCT anti-collision response is built from m_tag_information which
* points into the shared tag data buffer. After a slot switch the buffer
* may still contain the previous slot's UID if the FDS async load has not
* completed. A forced reload here ensures the correct UID is presented
* during the sniff session.
* A short settle delay follows to allow the reload to complete before
* the first field detection can trigger the anti-collision path. */
tag_emulation_load_data();
bsp_delay_ms(100);

/* Install sniff callback into the already-running tag emulation stack.
* Do NOT call tag_mode_enter() or sense_switch() here — those reinit
* NFCT and wipe the anti-collision data, breaking the emulation.
* The device must already be in emulator mode (hw mode --emulator)
* with a slot active before running this command. */
m_sniff_buf_len = 0;
m_sniff_cb_count = 0;
m_sniff_active = true;
nfc_tag_14a_set_sniff_cb(hf14a_sniff_frame_cb);

/* Wait for duration, yielding each ms so USB stack stays alive.
* Feed watchdog every iteration — WDT timeout is 5000ms and the
* main loop cannot feed it while we are blocking here. */
autotimer *p_at = bsp_obtain_timer(0);
while (NO_TIMEOUT_1MS(p_at, timeout_ms)) {
bsp_delay_ms(1);
bsp_wdt_feed();
}
bsp_return_timer(p_at);

/* Remove callback and restore normal sense state */
m_sniff_active = false;
nfc_tag_14a_clear_sniff_cb();
tag_emulation_sense_run(); /* restore slot-based sense state */

if (m_sniff_buf_len == 0) {
return data_frame_make(cmd, STATUS_HF_TAG_NO, 0, NULL);
}
return data_frame_make(cmd, STATUS_SUCCESS, m_sniff_buf_len, m_sniff_buf);
}

#endif

static cmd_data_map_t m_data_cmd_map[] = {
{ DATA_CMD_GET_APP_VERSION, NULL, cmd_processor_get_app_version, NULL },
{ DATA_CMD_CHANGE_DEVICE_MODE, NULL, cmd_processor_change_device_mode, NULL },
Expand Down Expand Up @@ -1808,6 +1925,9 @@ static cmd_data_map_t m_data_cmd_map[] = {

{ DATA_CMD_IOPROX_DECODE_RAW, NULL, cmd_processor_ioprox_decode_raw, NULL },
{ DATA_CMD_IOPROX_COMPOSE_ID, NULL, cmd_processor_ioprox_compose_id, NULL },
{ DATA_CMD_EM4X05_SCAN, before_reader_run, cmd_processor_em4x05_scan, NULL },
{ DATA_CMD_LF_SNIFF, before_reader_run, cmd_processor_lf_sniff, NULL },
{ DATA_CMD_HF14A_SNIFF, NULL, cmd_processor_hf14a_sniff, NULL },

#endif

Expand Down
1 change: 1 addition & 0 deletions firmware/application/src/app_status.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
/////////////////////////////////////////////////////////////////////
#define STATUS_LF_TAG_OK (0x40) // Some of the low -frequency cards are successful!
#define STATUS_LF_TAG_NO_FOUND (0x41) // Can't search for valid LF tags
#define STATUS_LF_TAG_LOGIN_REQUIRED (0x42) // Tag requires LOGIN before read

/////////////////////////////////////////////////////////////////////
// other status
Expand Down
5 changes: 5 additions & 0 deletions firmware/application/src/data_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@

#define DATA_CMD_HF14A_GET_CONFIG (2200)
#define DATA_CMD_HF14A_SET_CONFIG (2201)
#define DATA_CMD_HF14A_SNIFF (2020)

//
// ******************************************************************
Expand Down Expand Up @@ -173,4 +174,8 @@
#define DATA_CMD_IOPROX_SET_EMU_ID (5008)
#define DATA_CMD_IOPROX_GET_EMU_ID (5009)

#define DATA_CMD_EM4X05_SCAN (3030)
#define DATA_CMD_EM4X05_READSNIFF (3032)
#define DATA_CMD_LF_SNIFF (3031)

#endif
16 changes: 16 additions & 0 deletions firmware/application/src/rfid/nfctag/hf/nfc_14a.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ const uint16_t ats_fsdi_table[] = {
static volatile bool m_is_responded = false;
// Receiving buffer
static uint8_t m_nfc_rx_buffer[MAX_NFC_RX_BUFFER_SIZE] = { 0x00 };

/* Optional sniff callback — fires for every received frame */
static nfc_tag_14a_sniff_cb_t m_sniff_cb = NULL;

void nfc_tag_14a_set_sniff_cb(nfc_tag_14a_sniff_cb_t cb) {
m_sniff_cb = cb;
}

void nfc_tag_14a_clear_sniff_cb(void) {
m_sniff_cb = NULL;
}
static uint8_t m_nfc_tx_buffer[MAX_NFC_TX_BUFFER_SIZE] = { 0x00 };
// The N -secondary connection needs to use SAK, when the "third 'bit' in SAK is 1 is 1, the logo UID is incomplete
static uint8_t m_uid_incomplete_sak[] = { 0x04, 0xda, 0x17 };
Expand Down Expand Up @@ -326,6 +337,11 @@ void nfc_tag_14a_data_process(uint8_t *p_data) {
// Because of this error receiving event caused by this possible interference
return;
}

/* Sniff hook — fire before any tag response logic */
if (m_sniff_cb != NULL) {
m_sniff_cb(p_data, szDataBits);
}
// Manually draw frame, separate data and strange school inspection
#if !NFC_TAG_14A_RX_PARITY_AUTO_DEL_ENABLE
if (szDataBits >= 9) {
Expand Down
8 changes: 8 additions & 0 deletions firmware/application/src/rfid/nfctag/hf/nfc_14a.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ typedef struct {

// Communication reception function that needs to be implemented
typedef void (*nfc_tag_14a_reset_handler_t)(void);

/* Sniff callback — called for every received frame before the tag handler.
* data : raw frame bytes (after parity strip)
* szBits : number of bits received */
typedef void (*nfc_tag_14a_sniff_cb_t)(const uint8_t *data, uint16_t szBits);

void nfc_tag_14a_set_sniff_cb(nfc_tag_14a_sniff_cb_t cb);
void nfc_tag_14a_clear_sniff_cb(void);
typedef void (*nfc_tag_14a_state_handler_t)(uint8_t *data, uint16_t szBits);
typedef nfc_tag_14a_coll_res_reference_t *(*nfc_tag_14a_coll_handler_t)(void);

Expand Down
1 change: 1 addition & 0 deletions firmware/application/src/rfid/nfctag/tag_emulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ void tag_emulation_init(void);
void tag_emulation_save(void);

// Starting and ending of the emulation card
void tag_emulation_load_data(void);
void tag_emulation_sense_run(void);
void tag_emulation_sense_end(void);

Expand Down
5 changes: 5 additions & 0 deletions firmware/application/src/rfid/reader/lf/lf_125khz_radio.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#pragma once

#include "ble_main.h"
#include "nrfx_pwm.h"

/* Exposed so lf_gap.c can stop the PWM and drive LF_ANT_DRIVER directly
* to create clean field gaps without relying on PWM pin release state. */
extern nrfx_pwm_t m_pwm;

void lf_125khz_radio_init(void);
void lf_125khz_radio_uninit(void);
Expand Down
Loading
Loading