diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index a48b27e0..68661659 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -627,7 +627,7 @@ 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 card_buffer[7] = {0x00}; + uint8_t card_buffer[15] = {0x00}; status = scan_em410x(card_buffer); if (status != STATUS_LF_TAG_OK) { return data_frame_make(cmd, status, 0, NULL); diff --git a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c index b2ce0304..7b566334 100644 --- a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c +++ b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.c @@ -268,7 +268,7 @@ bool lf_tag_data_factory(uint8_t slot, tag_specific_type_t tag_type, uint8_t *ta */ bool lf_tag_em410x_data_factory(uint8_t slot, tag_specific_type_t tag_type) { // default id, must to align(4), more word... - uint8_t tag_id[5] = {0xDE, 0xAD, 0xBE, 0xEF, 0x88}; + uint8_t tag_id[13] = {0xDE, 0xAD, 0xBE, 0xEF, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; return lf_tag_data_factory(slot, tag_type, tag_id, sizeof(tag_id)); } diff --git a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.h b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.h index 3dabb30f..1b31e02c 100644 --- a/firmware/application/src/rfid/nfctag/lf/lf_tag_em.h +++ b/firmware/application/src/rfid/nfctag/lf/lf_tag_em.h @@ -5,7 +5,7 @@ #include "rfid_main.h" #include "tag_emulation.h" -#define LF_EM410X_TAG_ID_SIZE 5 +#define LF_EM410X_TAG_ID_SIZE 13 #define LF_HIDPROX_TAG_ID_SIZE 13 #define LF_VIKING_TAG_ID_SIZE 4 diff --git a/firmware/application/src/rfid/nfctag/lf/protocols/em410x.c b/firmware/application/src/rfid/nfctag/lf/protocols/em410x.c index cf7d543e..d4304a6d 100644 --- a/firmware/application/src/rfid/nfctag/lf/protocols/em410x.c +++ b/firmware/application/src/rfid/nfctag/lf/protocols/em410x.c @@ -15,11 +15,15 @@ #define EM_BITS_PER_ROW_COUNT (EM_COLUMN_COUNT + 1) #define EM_RAW_SIZE (64) -#define EM_DATA_SIZE (5) +#define EM_DECODED_BASE_DATA_SIZE (5) +#define EM_DECODED_EPILOGUE_SIZE (8) +#define EM_DATA_SIZE (EM_DECODED_BASE_DATA_SIZE + EM_DECODED_EPILOGUE_SIZE) #define EM_ROW_COUNT (10) #define EM_COLUMN_COUNT (4) #define EM_HEADER (0x1ff) // 9 bits of 1 +#define EM_ENCODED_DATA_HEADER (0xFF80000000000000ULL) + #define EM_T55XX_BLOCK_COUNT (3) #define EM_READ_TIME1_BASE (0x40) @@ -33,7 +37,7 @@ #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] = {}; +static nrf_pwm_values_wave_form_t m_em410x_pwm_seq_vals[EM_RAW_SIZE + EM_RAW_SIZE] = {}; nrf_pwm_sequence_t const m_em410x_pwm_seq = { .values.p_wave_form = m_em410x_pwm_seq_vals, @@ -53,7 +57,8 @@ size_t em410x_protocols_size = ARRAY_SIZE(em410x_protocols); typedef struct { uint8_t data[EM_DATA_SIZE]; uint64_t raw; - uint8_t raw_length; + uint64_t epilogue; + uint8_t length; manchester *modem; } em410x_codec; @@ -80,6 +85,17 @@ uint64_t em410x_raw_data(uint8_t *uid) { return raw; } +uint64_t em410x_raw_epilogue(uint8_t *uid) { + uint64_t raw = 0; + + for (int i = 0; i < EM_DECODED_EPILOGUE_SIZE; i++) { + raw <<= 8; + raw |= uid[EM_DECODED_BASE_DATA_SIZE + i]; + } + + 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; @@ -144,27 +160,24 @@ 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; + d->length = 0; + d->epilogue = 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) { + bool carry_bit = (d->epilogue >> 63) & 0b1; + + d->length++; + d->raw = (d->raw << 1) | carry_bit; + d->epilogue = (d->epilogue << 1) | bit; + + if (d->length < EM_RAW_SIZE + 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) { + if ((d->raw & EM_ENCODED_DATA_HEADER) != EM_ENCODED_DATA_HEADER) { return false; } @@ -192,6 +205,15 @@ bool em410x_decode_feed(em410x_codec *d, bool bit) { d->data[i >> 1] = data << 4; } } + + for (int i = 0; i < EM_DECODED_EPILOGUE_SIZE; i++) { + if ((d->epilogue & EM_ENCODED_DATA_HEADER) == EM_ENCODED_DATA_HEADER) { + d->data[EM_DECODED_BASE_DATA_SIZE + i] = 0; + } else { + d->data[EM_DECODED_BASE_DATA_SIZE + i] = (d->epilogue >> ((EM_DECODED_EPILOGUE_SIZE - 1 - i) * 8)) & 0XFF; + } + } + return pc == 0x00; // column parity } @@ -201,7 +223,8 @@ bool em410x_decoder_feed(em410x_codec *d, uint16_t interval) { manchester_feed(d->modem, (uint8_t)interval, bits, &bitlen); if (bitlen == -1) { d->raw = 0; - d->raw_length = 0; + d->length = 0; + d->epilogue = 0; return false; } for (int i = 0; i < bitlen; i++) { @@ -213,15 +236,21 @@ bool em410x_decoder_feed(em410x_codec *d, uint16_t interval) { }; 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); + uint64_t data[] = {em410x_raw_data(buf), em410x_raw_epilogue(buf)}; + uint8_t output_index = 0; + + for (int d = 0; d < 2; d++) { + for (int i = 0; i < EM_RAW_SIZE; i++) { + uint16_t msb = 0x00; + if (IS_SET(data[d], EM_RAW_SIZE - i - 1)) { + msb = (1 << 15); + } + m_em410x_pwm_seq_vals[output_index].channel_0 = msb | 32; + m_em410x_pwm_seq_vals[output_index].counter_top = 64; + output_index++; } - m_em410x_pwm_seq_vals[i].channel_0 = msb | 32; - m_em410x_pwm_seq_vals[i].counter_top = 64; } + return &m_em410x_pwm_seq; }; diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index b2c47e1d..67768508 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -405,8 +405,8 @@ def add_card_arg(parser: ArgumentParserNoExit, required=False): def before_exec(self, args: argparse.Namespace): if not super().before_exec(args): return False - if args.id is None or not re.match(r"^[a-fA-F0-9]{10}$", args.id): - raise ArgsParserError("ID must include 10 HEX symbols") + if args.id is None or not re.match(r"^[a-fA-F0-9]{26}$", args.id): + raise ArgsParserError("ID must include 26 HEX symbols") return True def args_parser(self) -> ArgumentParserNoExit: diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index f34889b3..41a50078 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -434,7 +434,7 @@ def em410x_scan(self): """ resp = self.device.send_cmd_sync(Command.EM410X_SCAN) if resp.status == Status.LF_TAG_OK: - resp.parsed = struct.unpack('!h5s', resp.data) # tag type + uid + resp.parsed = struct.unpack('!h13s', resp.data) # tag type + uid return resp @expect_response(Status.LF_TAG_OK) @@ -599,9 +599,9 @@ def em410x_set_emu_id(self, id: bytes): :param id_bytes: byte of the card number :return: """ - if len(id) != 5: - raise ValueError("The id bytes length must equal 5") - data = struct.pack('5s', id) + if len(id) != 13: + raise ValueError("The id bytes length must equal 13") + data = struct.pack('13s', id) return self.device.send_cmd_sync(Command.EM410X_SET_EMU_ID, data) @expect_response(Status.SUCCESS)