diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 52ce6b4..7b67468 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -78,6 +78,7 @@ #define DATA_CMD_HF14A_GET_CONFIG (2200) #define DATA_CMD_HF14A_SET_CONFIG (2201) +#define DATA_CMD_HF14A_SNIFF (2020) // // ****************************************************************** diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_14a.c b/firmware/application/src/rfid/nfctag/hf/nfc_14a.c index 7f208ac..d6fd0f6 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_14a.c +++ b/firmware/application/src/rfid/nfctag/hf/nfc_14a.c @@ -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) { diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_14a.h b/firmware/application/src/rfid/nfctag/hf/nfc_14a.h index e38b250..0d92022 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_14a.h +++ b/firmware/application/src/rfid/nfctag/hf/nfc_14a.h @@ -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); diff --git a/firmware/application/src/rfid/nfctag/tag_emulation.h b/firmware/application/src/rfid/nfctag/tag_emulation.h index 9b3173a..f1e88c2 100644 --- a/firmware/application/src/rfid/nfctag/tag_emulation.h +++ b/firmware/application/src/rfid/nfctag/tag_emulation.h @@ -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); diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index ec1ba12..3de02da 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -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): """ diff --git a/software/script/chameleon_enum.py b/software/script/chameleon_enum.py index 9d2dc26..a381346 100644 --- a/software/script/chameleon_enum.py +++ b/software/script/chameleon_enum.py @@ -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