Merge pull request #396 from nieldk/feat/hf14a-sniff

feat(hf): add ISO14443A reader frame capture (hf 14a sniff)
This commit is contained in:
GameTec-live
2026-04-02 12:32:26 +02:00
committed by GitHub
6 changed files with 43 additions and 0 deletions
+1
View File
@@ -78,6 +78,7 @@
#define DATA_CMD_HF14A_GET_CONFIG (2200)
#define DATA_CMD_HF14A_SET_CONFIG (2201)
#define DATA_CMD_HF14A_SNIFF (2020)
//
// ******************************************************************
@@ -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 };
@@ -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) {
@@ -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);
@@ -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);
+16
View File
@@ -425,6 +425,22 @@ class ChameleonCMD:
i += 14
return resp
def hf14a_sniff(self, timeout_ms: int = 5000):
"""
Capture ISO14443A reader frames while CU acts as a tag emulator.
The firmware installs a sniff callback into the HF14A stack for the
requested duration, then returns all captured frames packed as:
[2 bytes: bit count, big-endian] [N bytes: frame data, ceil(bits/8)] ...
:param timeout_ms: Listen duration in ms (1-30000, default 5000)
:return: Raw response — check .status and .data
"""
timeout_ms = max(1, min(30000, timeout_ms))
payload = bytes([(timeout_ms >> 8) & 0xFF, timeout_ms & 0xFF])
timeout_s = (timeout_ms // 1000) + 5
return self.device.send_cmd_sync(Command.HF14A_SNIFF, payload, timeout=timeout_s)
@expect_response(Status.SUCCESS)
def hf14a_get_config(self):
"""
+1
View File
@@ -75,6 +75,7 @@ class Command(enum.IntEnum):
MF1_CHECK_KEYS_ON_BLOCK = 2015
HF14A_GET_CONFIG = 2200
HF14A_SET_CONFIG = 2201
HF14A_SNIFF = 2020
EM410X_SCAN = 3000
EM410X_WRITE_TO_T55XX = 3001