From 6a317bdacc91cd942e337f22bbecbaddacc5c5f2 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Fri, 21 Aug 2026 12:45:46 +0800 Subject: [PATCH] Added CMD_HF_ICLASS_RAW Raw iCLASS reader exchange that leaves the field ON --- armsrc/appmain.c | 4 ++++ armsrc/iclass.c | 37 +++++++++++++++++++++++++++++++++++++ armsrc/iclass.h | 1 + include/pm3_cmd.h | 1 + 4 files changed, 43 insertions(+) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 56ad5970f..7ea067b97 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2549,6 +2549,10 @@ static void PacketReceived(PacketCommandNG *packet) { ReaderIClass(packet->data.asBytes); break; } + case CMD_HF_ICLASS_RAW: { + iClass_Raw(packet->data.asBytes); + break; + } case CMD_HF_ICLASS_EML_MEMSET: { FpgaDownloadAndGo_keep_EM(FPGA_BITSTREAM_HF_15); struct p { diff --git a/armsrc/iclass.c b/armsrc/iclass.c index c374d12ee..4a0456e4a 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1601,6 +1601,43 @@ out: switch_off(); } +// Raw iCLASS reader exchange that leaves the field ON +// The field is only dropped by CMD_HF_DROPFIELD (or a failed select). +void iClass_Raw(uint8_t *msg) { + uint8_t flags = msg[0]; + uint16_t rawlen = (uint16_t)msg[1] | ((uint16_t)msg[2] << 8); + uint8_t *raw = msg + 3; + + uint32_t start_time = 0, eof_time = 0; + + if (flags & 0x01) { // INIT: energize + select + Iso15693InitReader(); + picopass_hdr_t hdr = {0}; + if (select_iclass_tag(&hdr, false, &eof_time, false) == false) { + switch_off(); + reply_ng(CMD_HF_ICLASS_RAW, PM3_ERFTRANS, NULL, 0); + return; + } + if (rawlen == 0) { // scan: return the header, keep field ON + reply_ng(CMD_HF_ICLASS_RAW, PM3_SUCCESS, (uint8_t *)&hdr, sizeof(picopass_hdr_t)); + return; + } + start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; + } + + uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; + uint16_t resp_len = 0; + iclass_send_as_reader(raw, rawlen, &start_time, &eof_time, false); + int res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, + &eof_time, false, true, &resp_len); + if (res == PM3_SUCCESS && resp_len > 0) { + reply_ng(CMD_HF_ICLASS_RAW, PM3_SUCCESS, resp, resp_len); + } else { + reply_ng(CMD_HF_ICLASS_RAW, PM3_ECARDEXCHANGE, NULL, 0); + } + // field left ON; the host drops it via CMD_HF_DROPFIELD +} + bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) { uint8_t cmd_check[9] = { ICLASS_CMD_CHECK }; diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 2f2bd6d0e..9b3851394 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -48,6 +48,7 @@ void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string); void ReaderIClass(uint8_t *flags); +void iClass_Raw(uint8_t *msg); void iClass_WriteBlock(uint8_t *msg); void iclass_credit_epurse(iclass_credit_epurse_t *payload); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 6eef5820f..057ed9f15 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -798,6 +798,7 @@ typedef struct { #define CMD_HF_ICLASS_CREDIT_EPURSE 0x039C #define CMD_HF_ICLASS_RECOVER 0x039D #define CMD_HF_ICLASS_TEARBL 0x039E +#define CMD_HF_ICLASS_RAW 0x039F // For ISO1092 / FeliCa #define CMD_HF_FELICA_SIMULATE 0x03A0