From 6f21856e5d2c781b9cd1eb0b8a31ff5f1c84c5f5 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:08:55 +0200 Subject: [PATCH 01/23] Add long press --- firmware/application/src/app_main.c | 62 +++++++++++++++++++++++++---- firmware/application/src/settings.c | 54 +++++++++++++++++++++++++ firmware/application/src/settings.h | 8 +++- 3 files changed, 115 insertions(+), 9 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index ec240b0..1b0eb0d 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "nordic_common.h" #include "nrf.h" @@ -41,9 +42,17 @@ NRF_LOG_MODULE_REGISTER(); // Defining soft timers APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce + +static uint32_t m_last_btn_press = 0; + +static bool m_is_btn_long_press = false; + static bool m_is_b_btn_press = false; static bool m_is_a_btn_press = false; +static bool m_is_b_btn_release = false; +static bool m_is_a_btn_release = false; + // cpu reset reason static uint32_t m_reset_source; static uint32_t m_gpregret_val; @@ -152,12 +161,41 @@ static void timer_button_event_handle(void *arg) { if (settings_get_button_press_config('b') != SettingsButtonDisable) { NRF_LOG_INFO("BUTTON_LEFT"); // Button B? m_is_b_btn_press = true; + m_last_btn_press = app_timer_cnt_get(); } } if (pin == BUTTON_2) { if (settings_get_button_press_config('a') != SettingsButtonDisable) { NRF_LOG_INFO("BUTTON_RIGHT"); // Button A? m_is_a_btn_press = true; + m_last_btn_press = app_timer_cnt_get(); + } + } + } + + if (nrf_gpio_pin_read(pin) == 0) { + uint32_t now = app_timer_cnt_get(); + uint32_t ticks = app_timer_cnt_diff_compute(now, m_last_btn_press); + + uint32_t time = ticks * ((APP_TIMER_CONFIG_RTC_FREQUENCY + 1 ) * 1000 ) / APP_TIMER_CLOCK_FREQ; + + bool is_long_press = time > 1000; + + if (pin == BUTTON_1 && m_is_b_btn_press == true) { + // If button is disable, we can didn't dispatch key event. + if (settings_get_button_press_config('b') != SettingsButtonDisable) { + NRF_LOG_INFO("BUTTON_LEFT_RELEASE"); // Button B? + m_is_b_btn_release = true; + m_is_b_btn_press = false; + m_is_btn_long_press = is_long_press; + } + } + if (pin == BUTTON_2 && m_is_a_btn_press == true) { + if (settings_get_button_press_config('a') != SettingsButtonDisable) { + NRF_LOG_INFO("BUTTON_RIGHT_RELEASE"); // Button A? + m_is_a_btn_release = true; + m_is_a_btn_press = false; + m_is_btn_long_press = is_long_press; } } } @@ -173,7 +211,7 @@ static void button_init(void) { APP_ERROR_CHECK(err_code); // Configure SENSE mode, select false for sense configuration - nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(false); + nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); in_config.pull = NRF_GPIO_PIN_PULLDOWN; // Pulldown // Configure key binding POTR @@ -635,14 +673,22 @@ static void run_button_function_by_settings(settings_button_function_t sbf) { extern bool g_usb_led_marquee_enable; static void button_press_process(void) { // Make sure that one of the AB buttons has a click event - if (m_is_b_btn_press || m_is_a_btn_press) { - if (m_is_a_btn_press) { - run_button_function_by_settings(settings_get_button_press_config('a')); - m_is_a_btn_press = false; + if (m_is_b_btn_release || m_is_a_btn_release) { + if (m_is_a_btn_release) { + if(!m_is_btn_long_press) { + run_button_function_by_settings(settings_get_button_press_config('a')); + } else { + run_button_function_by_settings(settings_get_button_press_config('c')); + } + m_is_a_btn_release = false; } - if (m_is_b_btn_press) { - run_button_function_by_settings(settings_get_button_press_config('b')); - m_is_b_btn_press = false; + if (m_is_b_btn_release) { + if(!m_is_btn_long_press) { + run_button_function_by_settings(settings_get_button_press_config('b')); + } else { + run_button_function_by_settings(settings_get_button_press_config('d')); + } + m_is_b_btn_release = false; } // Disable led marquee for usb at button pressed. g_usb_led_marquee_enable = false; diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 18bbe15..5879f68 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -51,6 +51,10 @@ void settings_migrate(void) { settings_update_version_for_config(); break; + case 2: + config.button_a_long_press = SettingsButtonCloneIcUid; + config.button_b_long_press = SettingsButtonCloneIcUid; + /* * When needed migrations can be implemented like this: * @@ -167,6 +171,31 @@ uint8_t settings_get_button_press_config(char which) { return SettingsButtonDisable; } +/** + * @brief Get the long button press config + * + * @param which 'a' or 'b' + * @return uint8_t @link{ settings_button_function_t } + */ +uint8_t settings_get_long_button_press_config(char which) { + switch (which) { + case 'a': + case 'A': + return config.button_a_long_press; + + case 'b': + case 'B': + return config.button_b_long_press; + + default: + // can't to here. + APP_ERROR_CHECK_BOOL(false); + break; + } + // can't to here. + return SettingsButtonDisable; +} + /** * @brief Set the button press config * @@ -191,3 +220,28 @@ void settings_set_button_press_config(char which, uint8_t value) { break; } } + +/** + * @brief Set the long button press config + * + * @param which 'a' or 'b' + * @param value @link{ settings_button_function_t } + */ +void settings_set_long_button_press_config(char which, uint8_t value) { + switch (which) { + case 'a': + case 'A': + config.button_a_long_press = value; + break; + + case 'b': + case 'B': + config.button_b_long_press = value; + break; + + default: + // can't to here. + APP_ERROR_CHECK_BOOL(false); + break; + } +} diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index d1775f2..1713374 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -5,7 +5,7 @@ #include "utils.h" -#define SETTINGS_CURRENT_VERSION 2 +#define SETTINGS_CURRENT_VERSION 3 typedef enum { SettingsAnimationModeFull = 0U, @@ -36,6 +36,10 @@ typedef struct ALIGN_U32 { uint8_t button_a_press : 4; uint8_t button_b_press : 4; + // 1 byte + uint8_t button_a_long_press : 4; + uint8_t button_b_long_press : 4; + // 8 byte uint32_t reserved1; uint32_t reserved2; @@ -48,7 +52,9 @@ uint8_t settings_save_config(void); uint8_t settings_get_animation_config(void); void settings_set_animation_config(uint8_t value); uint8_t settings_get_button_press_config(char which); +uint8_t settings_get_long_button_press_config(char which); void settings_set_button_press_config(char which, uint8_t value); +void settings_set_long_button_press_config(char which, uint8_t value); bool is_settings_button_type_valid(char type); #endif From 06023d4121e44a856ac2daf21c372a0bcd285a50 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:18:47 +0200 Subject: [PATCH 02/23] Add long press command --- firmware/application/src/app_cmd.c | 25 +++++++++++++++++++++++++ firmware/application/src/data_cmd.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 9699c63..396d17f 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -146,6 +146,29 @@ data_frame_tx_t *cmd_processor_set_button_press_config(uint16_t cmd, uint16_t st return data_frame_make(cmd, status, 0, NULL); } +data_frame_tx_t *cmd_processor_get_long_button_press_config(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + uint8_t button_press_config; + if (length == 1 && is_settings_button_type_valid(data[0])) { + button_press_config = settings_get_long_button_press_config(data[0]); + status = STATUS_DEVICE_SUCCESS; + } else { + length = 0; + status = STATUS_PAR_ERR; + } + return data_frame_make(cmd, status, length, (uint8_t *)(&button_press_config)); +} + +data_frame_tx_t *cmd_processor_set_long_button_press_config(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + if (length == 2 && is_settings_button_type_valid(data[0])) { + settings_set_long_button_press_config(data[0], data[1]); + status = STATUS_DEVICE_SUCCESS; + } else { + length = 0; + status = STATUS_PAR_ERR; + } + return data_frame_make(cmd, status, 0, NULL); +} + #if defined(PROJECT_CHAMELEON_ULTRA) data_frame_tx_t *cmd_processor_14a_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { @@ -783,6 +806,8 @@ static cmd_data_map_t m_data_cmd_map[] = { { DATA_CMD_GET_BATTERY_INFO, NULL, cmd_processor_get_battery_info, NULL }, { DATA_CMD_GET_BUTTON_PRESS_CONFIG, NULL, cmd_processor_get_button_press_config, NULL }, { DATA_CMD_SET_BUTTON_PRESS_CONFIG, NULL, cmd_processor_set_button_press_config, NULL }, + { DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG, NULL, cmd_processor_get_long_button_press_config, NULL }, + { DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG, NULL, cmd_processor_set_long_button_press_config, NULL }, #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 98c9681..5b74c0f 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -33,6 +33,8 @@ #define DATA_CMD_GET_BATTERY_INFO (1025) #define DATA_CMD_GET_BUTTON_PRESS_CONFIG (1026) #define DATA_CMD_SET_BUTTON_PRESS_CONFIG (1027) +#define DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG (1028) +#define DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG (1029) // // ****************************************************************** From 1ff0be6ed8e8a1ba956ee80886a70ce91ebeca55 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:29:03 +0200 Subject: [PATCH 03/23] Add long press command --- software/script/chameleon_cli_unit.py | 10 +++++++++- software/script/chameleon_cmd.py | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 9f99ec9..35312b6 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1318,9 +1318,12 @@ class HWButtonSettingsGet(DeviceRequiredUnit): print("") for button in button_list: resp = self.cmd.get_button_press_fun(button) + resp_long = self.cmd.get_long_button_press_fun(button) button_fn = chameleon_cmd.ButtonPressFunction.from_int(resp.data[0]) + button_long_fn = chameleon_cmd.ButtonPressFunction.from_int(resp_long.data[0]) print(f" - {colorama.Fore.GREEN}{button}{colorama.Style.RESET_ALL}: {button_fn}") print(f" usage: {button_fn.usage()}") + print(f" long press usage: {button_long_fn.usage()}") print("") print(" - Successfully get button function from settings") @@ -1330,6 +1333,7 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() + parser.add_argument('-l', '--long', type=int, required=True, help="1 is Long or 0 Short", choices=[0, 1]) parser.add_argument('-b', type=str, required=True, help="Change the function of the pressed button(?).", choices=chameleon_cmd.ButtonType.list_str()) @@ -1344,5 +1348,9 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): button = chameleon_cmd.ButtonType.from_str(args.b) function = chameleon_cmd.ButtonPressFunction.from_int(args.f) - self.cmd.set_button_press_fun(button, function) + long = args.l == 1 + if long: + self.cmd.set_long_button_press_fun(button, function) + else: + self.cmd.set_button_press_fun(button, function) print(" - Successfully set button function to settings") diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 33f4e39..a3ef8c7 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -42,6 +42,9 @@ DATA_CMD_GET_BATTERY_INFO = 1025 DATA_CMD_GET_BUTTON_PRESS_CONFIG = 1026 DATA_CMD_SET_BUTTON_PRESS_CONFIG = 1027 +DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG = 1028 +DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG = 1029 + DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 DATA_CMD_MF1_NT_LEVEL_DETECT = 2002 @@ -769,6 +772,24 @@ class ChameleonCMD: bytearray([button, function]) ) + @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) + def get_long_button_press_fun(self, button: ButtonType): + """ + Get config of button press function + """ + return self.device.send_cmd_sync(DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG, 0x00, bytearray([button])) + + @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) + def set_long_button_press_fun(self, button: ButtonType, function: ButtonPressFunction): + """ + Set config of button press function + """ + return self.device.send_cmd_sync( + DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG, + 0x00, + bytearray([button, function]) + ) + if __name__ == '__main__': # connect to chameleon dev = chameleon_com.ChameleonCom() From 60cc62d3c9ea6902fd2966a3383f4940a96e7380 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:29:25 +0200 Subject: [PATCH 04/23] Add long press command --- firmware/application/src/data_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 5b74c0f..2737beb 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -33,8 +33,8 @@ #define DATA_CMD_GET_BATTERY_INFO (1025) #define DATA_CMD_GET_BUTTON_PRESS_CONFIG (1026) #define DATA_CMD_SET_BUTTON_PRESS_CONFIG (1027) -#define DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG (1028) -#define DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG (1029) +#define DATA_CMD_GET_LONG_BUTTON_PRESS_CONFIG (1028) +#define DATA_CMD_SET_LONG_BUTTON_PRESS_CONFIG (1029) // // ****************************************************************** From 6e9582f4f25e86ade744fced1e70fd1e2bdccfe7 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:32:49 +0200 Subject: [PATCH 05/23] Fix bug --- software/script/chameleon_cli_unit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 35312b6..94057c4 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1348,7 +1348,7 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): button = chameleon_cmd.ButtonType.from_str(args.b) function = chameleon_cmd.ButtonPressFunction.from_int(args.f) - long = args.l == 1 + long = args.long == 1 if long: self.cmd.set_long_button_press_fun(button, function) else: From 9db1dd37c02f3baabb7317729ae2ebfd298fa69b Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:34:31 +0200 Subject: [PATCH 06/23] Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e070f3..d46d712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,5 +51,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fixed compilation errors with GCC 12 (@Foxushka) - Added documentation for JLink (@xianglin1998) - Added support for ST-Link and debugging documentation (@derGraph) + - Added support for long-press of buttons ## [v1.0][2023-06-06] From b2851251d1d8076dbc554f753c7163d0bc57896d Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Wed, 23 Aug 2023 19:39:20 +0200 Subject: [PATCH 07/23] Forgot about this --- firmware/application/src/app_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 1b0eb0d..c09607e 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -678,7 +678,7 @@ static void button_press_process(void) { if(!m_is_btn_long_press) { run_button_function_by_settings(settings_get_button_press_config('a')); } else { - run_button_function_by_settings(settings_get_button_press_config('c')); + run_button_function_by_settings(settings_get_long_button_press_config('a')); } m_is_a_btn_release = false; } @@ -686,7 +686,7 @@ static void button_press_process(void) { if(!m_is_btn_long_press) { run_button_function_by_settings(settings_get_button_press_config('b')); } else { - run_button_function_by_settings(settings_get_button_press_config('d')); + run_button_function_by_settings(settings_get_long_button_press_config('b')); } m_is_b_btn_release = false; } From f45cf5b406084794bc2f2cc26dfb86e7462b65e7 Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Thu, 24 Aug 2023 08:46:42 +0200 Subject: [PATCH 08/23] Move log and add github username --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d46d712..c5ba688 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added support for long-press of buttons (@nemanjan00) - Changed `hw slot delete`, now it can always delete from slot. (@augustozanellato) - Refactor CI pipeline. (@augustozanellato) - Added offline copy EM card uid for btnpress.(@nemanjan00) @@ -51,6 +52,5 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fixed compilation errors with GCC 12 (@Foxushka) - Added documentation for JLink (@xianglin1998) - Added support for ST-Link and debugging documentation (@derGraph) - - Added support for long-press of buttons ## [v1.0][2023-06-06] From a01158f323e38ac0e13d5738c01be65a6fb1ac1a Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Thu, 24 Aug 2023 08:50:55 +0200 Subject: [PATCH 09/23] Remove parameter from --long --- software/script/chameleon_cli_unit.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 94057c4..8b98861 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1333,7 +1333,8 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() - parser.add_argument('-l', '--long', type=int, required=True, help="1 is Long or 0 Short", choices=[0, 1]) + parser.add_argument('-l', '--long', action='store_true', default=False, + help="set keybinding for long-press") parser.add_argument('-b', type=str, required=True, help="Change the function of the pressed button(?).", choices=chameleon_cmd.ButtonType.list_str()) @@ -1348,7 +1349,7 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): button = chameleon_cmd.ButtonType.from_str(args.b) function = chameleon_cmd.ButtonPressFunction.from_int(args.f) - long = args.long == 1 + long = args.long == True if long: self.cmd.set_long_button_press_fun(button, function) else: From a856936203f2d3d26bbe896f941ec2d2d59a8b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nemanja=20Nedeljkovi=C4=87?= Date: Thu, 24 Aug 2023 09:51:35 +0200 Subject: [PATCH 10/23] Update firmware/application/src/app_main.c Thanks @doegox Co-authored-by: Philippe Teuwen --- firmware/application/src/app_main.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index c09607e..6291142 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -177,9 +177,7 @@ static void timer_button_event_handle(void *arg) { uint32_t now = app_timer_cnt_get(); uint32_t ticks = app_timer_cnt_diff_compute(now, m_last_btn_press); - uint32_t time = ticks * ((APP_TIMER_CONFIG_RTC_FREQUENCY + 1 ) * 1000 ) / APP_TIMER_CLOCK_FREQ; - - bool is_long_press = time > 1000; + bool is_long_press = time > APP_TIMER_TICKS(1000); if (pin == BUTTON_1 && m_is_b_btn_press == true) { // If button is disable, we can didn't dispatch key event. From 728472e672346a156af4d1d7209dbb6047060c08 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 09:55:01 +0200 Subject: [PATCH 11/23] comment accepted too fast before I fixed it :) --- firmware/application/src/app_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 6291142..6379d6c 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -177,7 +177,7 @@ static void timer_button_event_handle(void *arg) { uint32_t now = app_timer_cnt_get(); uint32_t ticks = app_timer_cnt_diff_compute(now, m_last_btn_press); - bool is_long_press = time > APP_TIMER_TICKS(1000); + bool is_long_press = ticks > APP_TIMER_TICKS(1000); if (pin == BUTTON_1 && m_is_b_btn_press == true) { // If button is disable, we can didn't dispatch key event. From 1ebeb9b4618e5d5fb32daa57556a2647da4e069b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 10:44:19 +0200 Subject: [PATCH 12/23] fix btnpress info dump --- software/script/chameleon_cli_unit.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 8b98861..a18690c 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1321,9 +1321,10 @@ class HWButtonSettingsGet(DeviceRequiredUnit): resp_long = self.cmd.get_long_button_press_fun(button) button_fn = chameleon_cmd.ButtonPressFunction.from_int(resp.data[0]) button_long_fn = chameleon_cmd.ButtonPressFunction.from_int(resp_long.data[0]) - print(f" - {colorama.Fore.GREEN}{button}{colorama.Style.RESET_ALL}: {button_fn}") + print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}short{colorama.Style.RESET_ALL}: {button_fn}") print(f" usage: {button_fn.usage()}") - print(f" long press usage: {button_long_fn.usage()}") + print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}long {colorama.Style.RESET_ALL}: {button_long_fn}") + print(f" usage: {button_long_fn.usage()}") print("") print(" - Successfully get button function from settings") From 3baa0e6633773e81f36ae59070dfecb317231ba0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 10:54:22 +0200 Subject: [PATCH 13/23] button press logs --- firmware/application/src/app_main.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 6379d6c..fa56dbf 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -157,16 +157,16 @@ static void timer_button_event_handle(void *arg) { // Check here if the current GPIO is at the pressed level if (nrf_gpio_pin_read(pin) == 1) { if (pin == BUTTON_1) { - // If button is disable, we can didn't dispatch key event. + // If button is disabled, we can't dispatch key event. if (settings_get_button_press_config('b') != SettingsButtonDisable) { - NRF_LOG_INFO("BUTTON_LEFT"); // Button B? + NRF_LOG_INFO("BUTTON_B_PRESS"); m_is_b_btn_press = true; m_last_btn_press = app_timer_cnt_get(); } } if (pin == BUTTON_2) { if (settings_get_button_press_config('a') != SettingsButtonDisable) { - NRF_LOG_INFO("BUTTON_RIGHT"); // Button A? + NRF_LOG_INFO("BUTTON_A_PRESS"); m_is_a_btn_press = true; m_last_btn_press = app_timer_cnt_get(); } @@ -180,19 +180,27 @@ static void timer_button_event_handle(void *arg) { bool is_long_press = ticks > APP_TIMER_TICKS(1000); if (pin == BUTTON_1 && m_is_b_btn_press == true) { - // If button is disable, we can didn't dispatch key event. + // If button is disabled, we can't dispatch key event. if (settings_get_button_press_config('b') != SettingsButtonDisable) { - NRF_LOG_INFO("BUTTON_LEFT_RELEASE"); // Button B? m_is_b_btn_release = true; m_is_b_btn_press = false; + if (!is_long_press) { + NRF_LOG_INFO("BUTTON_B_RELEASE_SHORT"); + } else { + NRF_LOG_INFO("BUTTON_B_RELEASE_LONG"); + } m_is_btn_long_press = is_long_press; } } if (pin == BUTTON_2 && m_is_a_btn_press == true) { if (settings_get_button_press_config('a') != SettingsButtonDisable) { - NRF_LOG_INFO("BUTTON_RIGHT_RELEASE"); // Button A? m_is_a_btn_release = true; m_is_a_btn_press = false; + if (!is_long_press) { + NRF_LOG_INFO("BUTTON_A_RELEASE_SHORT"); + } else { + NRF_LOG_INFO("BUTTON_A_RELEASE_LONG"); + } m_is_btn_long_press = is_long_press; } } From 585748e302c788d5b36a9f414c60157383f5a2ca Mon Sep 17 00:00:00 2001 From: dxl <64101226@qq.com> Date: Thu, 24 Aug 2023 21:20:01 +0800 Subject: [PATCH 14/23] Fix the space allocation bug and initialization bug in the settings. --- firmware/application/src/settings.c | 16 ++++++++++++---- firmware/application/src/settings.h | 15 +++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 5879f68..4b11220 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -29,15 +29,24 @@ void settings_update_version_for_config(void) { config.version = SETTINGS_CURRENT_VERSION; } +// add on version2 void settings_init_button_press_config(void) { config.button_a_press = SettingsButtonCycleSlot; config.button_b_press = SettingsButtonCycleSlotDec; } +// add on version3 +void settings_init_button_long_press_config(void) { + config.button_a_long_press = SettingsButtonCloneIcUid; + config.button_b_long_press = SettingsButtonCloneIcUid; +} + void settings_init_config(void) { settings_update_version_for_config(); + // add on version1 config.animation_config = SettingsAnimationModeFull; settings_init_button_press_config(); + settings_init_button_long_press_config(); } void settings_migrate(void) { @@ -48,12 +57,11 @@ void settings_migrate(void) { case 1: settings_init_button_press_config(); - settings_update_version_for_config(); - break; case 2: - config.button_a_long_press = SettingsButtonCloneIcUid; - config.button_b_long_press = SettingsButtonCloneIcUid; + settings_init_button_long_press_config(); + settings_update_version_for_config(); + break; /* * When needed migrations can be implemented like this: diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index 1713374..fb55918 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -30,7 +30,7 @@ typedef struct ALIGN_U32 { // 1 byte uint8_t animation_config : 2; - uint8_t reserved0 : 6; + uint8_t reserved0 : 6; // If you are add switch field, reallocating me. // 1 byte uint8_t button_a_press : 4; @@ -40,9 +40,16 @@ typedef struct ALIGN_U32 { uint8_t button_a_long_press : 4; uint8_t button_b_long_press : 4; - // 8 byte - uint32_t reserved1; - uint32_t reserved2; + // 7 byte + uint32_t reserved1 : 24; // If you are add bigValue(not 1 or 0) field, reallocating me. + uint32_t reserved2; // see top. + + /* + * Warnning !!!!!!!!!!!!!!!!!!!!!! <------------- + * If you need to add settings, + * please be sure to consult the documentation of the bit field + * and fully use the space of this structure before considering reallocating memory space. + */ } settings_data_t; void settings_init_config(void); From 8d75ae45c447481805d16d1b3c958dd84440fb01 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 16:49:40 +0200 Subject: [PATCH 15/23] clearer(?) comments on settings migration --- firmware/application/src/settings.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 4b11220..93ef105 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -60,25 +60,15 @@ void settings_migrate(void) { case 2: settings_init_button_long_press_config(); - settings_update_version_for_config(); - break; /* - * When needed migrations can be implemented like this: - * - * case 1: - * config->new_field = some_default_value; - * case 2: - * config->another_new_field = some_default_value; - * case 3: - * config->another_new_field = some_default_value; - * break; - * - * Note that the `break` statement should only be used on the last migration step, all the previous steps must fall + * Add new migration steps ABOVE THIS COMMENT + * `settings_update_version_for_config()` and `break` statements should only be used on the last migration step, all the previous steps must fall * through to the next case. - * - * Note that the `settings_update_version_for_config` function should only be used on the last migration step. */ + + settings_update_version_for_config(); + break; default: NRF_LOG_ERROR("Unsupported configuration migration attempted! (%d -> %d)", config.version, SETTINGS_CURRENT_VERSION); break; From 7f569113a0b802defb394b4399aaf266907e2294 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 17:00:05 +0200 Subject: [PATCH 16/23] CLI check python version --- software/script/chameleon_cli_main.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 0f2f515..32b5819 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -92,6 +92,9 @@ class ChameleonCLI: start listen input. :return: """ + if sys.version_info < (3,9): + raise Exception("This script requires at least Python 3.9") + self.print_banner() closing = False while True: From 938f2b312c92153fd7f1f598a162af9c77ee615f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 17:41:18 +0200 Subject: [PATCH 17/23] offline copy IC/ID: don't skip HF if LK ok --- firmware/application/src/app_main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index fa56dbf..1c0c11f 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -574,8 +574,6 @@ static void btn_fn_copy_ic_uid(void) { tag_emulation_load_by_buffer(TAG_TYPE_EM410X, false); NRF_LOG_INFO("Offline LF uid copied") offline_status_ok(); - // no need to check for HF tag if we already cloned a LF tag - goto exit; } else { NRF_LOG_INFO("No LF tag found"); offline_status_error(); From 727cd5e6fabedf8313862493b089c6a36e86ef66 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 24 Aug 2023 18:42:27 +0200 Subject: [PATCH 18/23] CRLF and typo --- .../application/src/rfid/nfctag/hf/nfc_ntag.c | 602 +++++++++--------- .../application/src/rfid/nfctag/hf/nfc_ntag.h | 78 +-- .../dfu_key/{warnning.txt => warning.txt} | 0 3 files changed, 340 insertions(+), 340 deletions(-) rename resource/dfu_key/{warnning.txt => warning.txt} (100%) diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_ntag.c b/firmware/application/src/rfid/nfctag/hf/nfc_ntag.c index 3ffdf99..310548e 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_ntag.c +++ b/firmware/application/src/rfid/nfctag/hf/nfc_ntag.c @@ -1,301 +1,301 @@ -#include - -#include "nfc_ntag.h" -#include "nfc_14a.h" -#include "fds_util.h" -#include "tag_persistence.h" - -#define NRF_LOG_MODULE_NAME tag_ntag -#include "nrf_log.h" -#include "nrf_log_ctrl.h" -#include "nrf_log_default_backends.h" -NRF_LOG_MODULE_REGISTER(); - -#define NTAG213_VERSION 0x0F -#define NTAG215_VERSION 0x11 -#define NTAG216_VERSION 0x13 - -// NTAG COMMANDS -#define CMD_GET_VERSION 0x60 -#define CMD_READ 0x30 -#define CMD_FAST_READ 0x3A -#define CMD_WRITE 0xA2 -#define CMD_COMPAT_WRITE 0xA0 -#define CMD_READ_CNT 0x39 -#define CMD_PWD_AUTH 0x1B -#define CMD_READ_SIG 0x3C - -// MEMORY LAYOUT STUFF, addresses and sizes in bytes -// UID stuff -#define UID_CL1_ADDRESS 0x00 -#define UID_CL1_SIZE 3 -#define UID_BCC1_ADDRESS 0x03 -#define UID_CL2_ADDRESS 0x04 -#define UID_CL2_SIZE 4 -#define UID_BCC2_ADDRESS 0x08 -// LockBytes stuff -#define STATIC_LOCKBYTE_0_ADDRESS 0x0A -#define STATIC_LOCKBYTE_1_ADDRESS 0x0B -// CONFIG stuff -#define NTAG213_CONFIG_AREA_START_ADDRESS 0xA4 // 4 * 0x29 -#define NTAG215_CONFIG_AREA_START_ADDRESS 0x20C // 4 * 0x83 -#define NTAG216_CONFIG_AREA_START_ADDRESS 0x38C // 4 * 0xE3 -#define CONFIG_AREA_SIZE 8 -// CONFIG offsets, relative to config start address -#define CONF_AUTH0_OFFSET 0x03 -#define CONF_ACCESS_OFFSET 0x04 -#define CONF_PASSWORD_OFFSET 0x08 -#define CONF_PACK_OFFSET 0x0C - -// WRITE STUFF -#define BYTES_PER_WRITE 4 -#define PAGE_WRITE_MIN 0x02 - -// CONFIG masks to check individual needed bits -#define CONF_ACCESS_PROT 0x80 - -#define VERSION_INFO_LENGTH 8 //8 bytes info lenght + crc - -#define BYTES_PER_READ 16 - -// SIGNATURE Lenght -#define SIGNATURE_LENGTH 32 - -// NTAG215_Version[7] mean: -// 0x0F ntag213 -// 0x11 ntag215 -// 0x13 ntag216 -const uint8_t ntagVersion[8] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03}; -/* pwd auth for amiibo */ -uint8_t ntagPwdOK[2] = {0x80, 0x80}; - -// Data structure pointer to the label information -static nfc_tag_ntag_information_t *m_tag_information = NULL; -// Define and use shadow anti -collision resources -static nfc_tag_14a_coll_res_referen_t m_shadow_coll_res; -//Define and use NTAG special communication buffer -static nfc_tag_ntag_tx_buffer_t m_tag_tx_buffer; -// Save the specific type of NTAG currently being simulated -static tag_specific_type_t m_tag_type; - -static int get_block_max_by_tag_type(tag_specific_type_t tag_type) { - int block_max; - switch (tag_type) { - case TAG_TYPE_NTAG_213: - block_max = NTAG213_PAGES; - break; - default: - case TAG_TYPE_NTAG_215: - block_max = NTAG215_PAGES; - break; - case TAG_TYPE_NTAG_216: - block_max = NTAG216_PAGES; - break; - } - return block_max; -} - -static int get_block_cfg_by_tag_type(tag_specific_type_t tag_type) { - int block_max; - switch (tag_type) { - case TAG_TYPE_NTAG_213: - block_max = NTAG213_CONFIG_AREA_START_ADDRESS; - break; - default: - case TAG_TYPE_NTAG_215: - block_max = NTAG215_CONFIG_AREA_START_ADDRESS; - break; - case TAG_TYPE_NTAG_216: - block_max = NTAG216_CONFIG_AREA_START_ADDRESS; - break; - } - return block_max; -} - -void nfc_tag_ntag_state_handler(uint8_t *p_data, uint16_t szDataBits) { - uint8_t command = p_data[0]; - uint8_t block_num = p_data[1]; - - switch (command) { - case CMD_GET_VERSION: - memcpy(m_tag_tx_buffer.tx_buffer, ntagVersion, 8); - switch (m_tag_type) { - case TAG_TYPE_NTAG_213: - m_tag_tx_buffer.tx_buffer[6] = NTAG213_VERSION; - break; - default: - case TAG_TYPE_NTAG_215: - m_tag_tx_buffer.tx_buffer[6] = NTAG215_VERSION; - break; - case TAG_TYPE_NTAG_216: - m_tag_tx_buffer.tx_buffer[6] = NTAG216_VERSION; - break; - } - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, 8, true); - break; - case CMD_READ: - if (block_num < get_block_max_by_tag_type(m_tag_type)) { - for (int block = 0; block < 4; block++) { - memcpy(m_tag_tx_buffer.tx_buffer + block * 4, m_tag_information->memory[block_num + block], NFC_TAG_NTAG_DATA_SIZE); - } - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, BYTES_PER_READ, true); - } else { - nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBIV, 4); - } - break; - case CMD_FAST_READ: { - uint8_t end_block_num = p_data[2]; - if ((block_num > end_block_num) || (block_num >= get_block_max_by_tag_type(m_tag_type)) || (end_block_num >= get_block_max_by_tag_type(m_tag_type))) { - nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBV, 4); - break; - } - for (int block = block_num; block <= end_block_num; block++) { - memcpy(m_tag_tx_buffer.tx_buffer + (block - block_num) * 4, m_tag_information->memory[block], NFC_TAG_NTAG_DATA_SIZE); - } - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, (end_block_num - block_num + 1) * NFC_TAG_NTAG_DATA_SIZE, true); - break; - } - case CMD_WRITE: - // TODO - nfc_tag_14a_tx_nbit_delay_window(ACK_VALUE, 4); - break; - case CMD_COMPAT_WRITE: - // TODO - break; - case CMD_PWD_AUTH: { - /* TODO: IMPLEMENT COUNTER AUTHLIM */ - uint8_t Password[4]; - memcpy(Password, m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 4); - if (Password[0] != p_data[1] || Password[1] != p_data[2] || Password[2] != p_data[3] || Password[3] != p_data[4]) { - nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBIV, 4); - break; - } - /* Authenticate the user */ - //RESET AUTHLIM COUNTER, CURRENTLY NOT IMPLEMENTED - // TODO - /* Send the PACK value back */ - if (m_tag_information->config.mode_uid_magic) { - nfc_tag_14a_tx_bytes(ntagPwdOK, 2, true); - } else { - nfc_tag_14a_tx_bytes(m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 2, true); - } - break; - } - case CMD_READ_SIG: - memset(m_tag_tx_buffer.tx_buffer, 0xCA, SIGNATURE_LENGTH); - nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, SIGNATURE_LENGTH, true); - break; - } - return; -} - -nfc_tag_14a_coll_res_referen_t *get_ntag_coll_res() { - // Use a separate anti -conflict information instead of using the information in the sector - m_shadow_coll_res.sak = m_tag_information->res_coll.sak; - m_shadow_coll_res.atqa = m_tag_information->res_coll.atqa; - m_shadow_coll_res.uid = m_tag_information->res_coll.uid; - m_shadow_coll_res.size = &(m_tag_information->res_coll.size); - m_shadow_coll_res.ats = &(m_tag_information->res_coll.ats); - // Finally, a shadow data structure pointer with only reference, no physical shadow, - return &m_shadow_coll_res; -} - -void nfc_tag_ntag_reset_handler() { - // TODO -} - -static int get_information_size_by_tag_type(tag_specific_type_t type) { - return sizeof(nfc_tag_14a_coll_res_entity_t) + sizeof(nfc_tag_ntag_configure_t) + (get_block_max_by_tag_type(type) * NFC_TAG_NTAG_DATA_SIZE); -} - -/** @brief ntag's callback before saving data - * @param type detailed label type - * @param buffer data buffer - * @return to be saved, the length of the data that needs to be saved, it means not saved when 0 - */ -int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) { - if (m_tag_type != TAG_TYPE_UNKNOWN) { - // Save the corresponding size data according to the current label type - return get_information_size_by_tag_type(type); - } else { - return 0; - } -} - -int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer) { - int info_size = get_information_size_by_tag_type(type); - if (buffer->length >= info_size) { - // Convert the data buffer to NTAG structure type - m_tag_information = (nfc_tag_ntag_information_t *)buffer->buffer; - // The specific type of NTAG that is simulated by the cache - m_tag_type = type; - // Register 14A communication management interface - nfc_tag_14a_handler_t handler_for_14a = { - .get_coll_res = get_ntag_coll_res, - .cb_state = nfc_tag_ntag_state_handler, - .cb_reset = nfc_tag_ntag_reset_handler, - }; - nfc_tag_14a_set_handler(&handler_for_14a); - NRF_LOG_INFO("HF ntag data load finish."); - } else { - NRF_LOG_ERROR("nfc_tag_ntag_information_t too big."); - } - return info_size; -} - -// Initialized NTAG factory data -bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type) { - // default ntag data - uint8_t default_p0[] = { 0x04, 0x68, 0x95, 0x71 }; - uint8_t default_p1[] = { 0xFA, 0x5C, 0x64, 0x80 }; - uint8_t default_p2[] = { 0x42, 0x48, 0x0F, 0xE0 }; - - // default ntag info - nfc_tag_ntag_information_t ntag_tmp_information; - nfc_tag_ntag_information_t *p_ntag_information; - p_ntag_information = &ntag_tmp_information; - int block_max = get_block_max_by_tag_type(tag_type); - for (int block = 0; block < block_max; block++) { - if (block == 0) { - memcpy(p_ntag_information->memory[block], default_p0, NFC_TAG_NTAG_DATA_SIZE); - } - if (block == 1) { - memcpy(p_ntag_information->memory[block], default_p1, NFC_TAG_NTAG_DATA_SIZE); - } - if (block == 2) { - memcpy(p_ntag_information->memory[block], default_p2, NFC_TAG_NTAG_DATA_SIZE); - } - } - - // default ntag auto ant-collision res - p_ntag_information->res_coll.atqa[0] = 0x44; - p_ntag_information->res_coll.atqa[1] = 0x00; - p_ntag_information->res_coll.sak[0] = 0x00; - p_ntag_information->res_coll.uid[0] = 0x04; - p_ntag_information->res_coll.uid[1] = 0x68; - p_ntag_information->res_coll.uid[2] = 0x95; - p_ntag_information->res_coll.uid[3] = 0x71; - p_ntag_information->res_coll.uid[4] = 0xFA; - p_ntag_information->res_coll.uid[5] = 0x5C; - p_ntag_information->res_coll.uid[6] = 0x64; - p_ntag_information->res_coll.size = NFC_TAG_14A_UID_DOUBLE_SIZE; - p_ntag_information->res_coll.ats.length = 0; - - // default ntag config - p_ntag_information->config.mode_uid_magic = true; - p_ntag_information->config.detection_enable = false; - - // save data to flash - tag_sense_type_t sense_type = get_sense_type_from_tag_type(tag_type); - fds_slot_record_map_t map_info; - get_fds_map_by_slot_sense_type_for_dump(slot, sense_type, &map_info); - int info_size = get_information_size_by_tag_type(tag_type); // auto 4 byte align. - NRF_LOG_INFO("NTAG info size: %d", info_size); - bool ret = fds_write_sync(map_info.id, map_info.key, info_size / 4, p_ntag_information); - if (ret) { - NRF_LOG_INFO("Factory slot data success."); - } else { - NRF_LOG_ERROR("Factory slot data error."); - } - return ret; -} +#include + +#include "nfc_ntag.h" +#include "nfc_14a.h" +#include "fds_util.h" +#include "tag_persistence.h" + +#define NRF_LOG_MODULE_NAME tag_ntag +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" +NRF_LOG_MODULE_REGISTER(); + +#define NTAG213_VERSION 0x0F +#define NTAG215_VERSION 0x11 +#define NTAG216_VERSION 0x13 + +// NTAG COMMANDS +#define CMD_GET_VERSION 0x60 +#define CMD_READ 0x30 +#define CMD_FAST_READ 0x3A +#define CMD_WRITE 0xA2 +#define CMD_COMPAT_WRITE 0xA0 +#define CMD_READ_CNT 0x39 +#define CMD_PWD_AUTH 0x1B +#define CMD_READ_SIG 0x3C + +// MEMORY LAYOUT STUFF, addresses and sizes in bytes +// UID stuff +#define UID_CL1_ADDRESS 0x00 +#define UID_CL1_SIZE 3 +#define UID_BCC1_ADDRESS 0x03 +#define UID_CL2_ADDRESS 0x04 +#define UID_CL2_SIZE 4 +#define UID_BCC2_ADDRESS 0x08 +// LockBytes stuff +#define STATIC_LOCKBYTE_0_ADDRESS 0x0A +#define STATIC_LOCKBYTE_1_ADDRESS 0x0B +// CONFIG stuff +#define NTAG213_CONFIG_AREA_START_ADDRESS 0xA4 // 4 * 0x29 +#define NTAG215_CONFIG_AREA_START_ADDRESS 0x20C // 4 * 0x83 +#define NTAG216_CONFIG_AREA_START_ADDRESS 0x38C // 4 * 0xE3 +#define CONFIG_AREA_SIZE 8 +// CONFIG offsets, relative to config start address +#define CONF_AUTH0_OFFSET 0x03 +#define CONF_ACCESS_OFFSET 0x04 +#define CONF_PASSWORD_OFFSET 0x08 +#define CONF_PACK_OFFSET 0x0C + +// WRITE STUFF +#define BYTES_PER_WRITE 4 +#define PAGE_WRITE_MIN 0x02 + +// CONFIG masks to check individual needed bits +#define CONF_ACCESS_PROT 0x80 + +#define VERSION_INFO_LENGTH 8 //8 bytes info lenght + crc + +#define BYTES_PER_READ 16 + +// SIGNATURE Lenght +#define SIGNATURE_LENGTH 32 + +// NTAG215_Version[7] mean: +// 0x0F ntag213 +// 0x11 ntag215 +// 0x13 ntag216 +const uint8_t ntagVersion[8] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03}; +/* pwd auth for amiibo */ +uint8_t ntagPwdOK[2] = {0x80, 0x80}; + +// Data structure pointer to the label information +static nfc_tag_ntag_information_t *m_tag_information = NULL; +// Define and use shadow anti -collision resources +static nfc_tag_14a_coll_res_referen_t m_shadow_coll_res; +//Define and use NTAG special communication buffer +static nfc_tag_ntag_tx_buffer_t m_tag_tx_buffer; +// Save the specific type of NTAG currently being simulated +static tag_specific_type_t m_tag_type; + +static int get_block_max_by_tag_type(tag_specific_type_t tag_type) { + int block_max; + switch (tag_type) { + case TAG_TYPE_NTAG_213: + block_max = NTAG213_PAGES; + break; + default: + case TAG_TYPE_NTAG_215: + block_max = NTAG215_PAGES; + break; + case TAG_TYPE_NTAG_216: + block_max = NTAG216_PAGES; + break; + } + return block_max; +} + +static int get_block_cfg_by_tag_type(tag_specific_type_t tag_type) { + int block_max; + switch (tag_type) { + case TAG_TYPE_NTAG_213: + block_max = NTAG213_CONFIG_AREA_START_ADDRESS; + break; + default: + case TAG_TYPE_NTAG_215: + block_max = NTAG215_CONFIG_AREA_START_ADDRESS; + break; + case TAG_TYPE_NTAG_216: + block_max = NTAG216_CONFIG_AREA_START_ADDRESS; + break; + } + return block_max; +} + +void nfc_tag_ntag_state_handler(uint8_t *p_data, uint16_t szDataBits) { + uint8_t command = p_data[0]; + uint8_t block_num = p_data[1]; + + switch (command) { + case CMD_GET_VERSION: + memcpy(m_tag_tx_buffer.tx_buffer, ntagVersion, 8); + switch (m_tag_type) { + case TAG_TYPE_NTAG_213: + m_tag_tx_buffer.tx_buffer[6] = NTAG213_VERSION; + break; + default: + case TAG_TYPE_NTAG_215: + m_tag_tx_buffer.tx_buffer[6] = NTAG215_VERSION; + break; + case TAG_TYPE_NTAG_216: + m_tag_tx_buffer.tx_buffer[6] = NTAG216_VERSION; + break; + } + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, 8, true); + break; + case CMD_READ: + if (block_num < get_block_max_by_tag_type(m_tag_type)) { + for (int block = 0; block < 4; block++) { + memcpy(m_tag_tx_buffer.tx_buffer + block * 4, m_tag_information->memory[block_num + block], NFC_TAG_NTAG_DATA_SIZE); + } + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, BYTES_PER_READ, true); + } else { + nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBIV, 4); + } + break; + case CMD_FAST_READ: { + uint8_t end_block_num = p_data[2]; + if ((block_num > end_block_num) || (block_num >= get_block_max_by_tag_type(m_tag_type)) || (end_block_num >= get_block_max_by_tag_type(m_tag_type))) { + nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBV, 4); + break; + } + for (int block = block_num; block <= end_block_num; block++) { + memcpy(m_tag_tx_buffer.tx_buffer + (block - block_num) * 4, m_tag_information->memory[block], NFC_TAG_NTAG_DATA_SIZE); + } + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, (end_block_num - block_num + 1) * NFC_TAG_NTAG_DATA_SIZE, true); + break; + } + case CMD_WRITE: + // TODO + nfc_tag_14a_tx_nbit_delay_window(ACK_VALUE, 4); + break; + case CMD_COMPAT_WRITE: + // TODO + break; + case CMD_PWD_AUTH: { + /* TODO: IMPLEMENT COUNTER AUTHLIM */ + uint8_t Password[4]; + memcpy(Password, m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 4); + if (Password[0] != p_data[1] || Password[1] != p_data[2] || Password[2] != p_data[3] || Password[3] != p_data[4]) { + nfc_tag_14a_tx_nbit_delay_window(NAK_INVALID_OPERATION_TBIV, 4); + break; + } + /* Authenticate the user */ + //RESET AUTHLIM COUNTER, CURRENTLY NOT IMPLEMENTED + // TODO + /* Send the PACK value back */ + if (m_tag_information->config.mode_uid_magic) { + nfc_tag_14a_tx_bytes(ntagPwdOK, 2, true); + } else { + nfc_tag_14a_tx_bytes(m_tag_information->memory[get_block_cfg_by_tag_type(m_tag_type) + CONF_PASSWORD_OFFSET], 2, true); + } + break; + } + case CMD_READ_SIG: + memset(m_tag_tx_buffer.tx_buffer, 0xCA, SIGNATURE_LENGTH); + nfc_tag_14a_tx_bytes(m_tag_tx_buffer.tx_buffer, SIGNATURE_LENGTH, true); + break; + } + return; +} + +nfc_tag_14a_coll_res_referen_t *get_ntag_coll_res() { + // Use a separate anti -conflict information instead of using the information in the sector + m_shadow_coll_res.sak = m_tag_information->res_coll.sak; + m_shadow_coll_res.atqa = m_tag_information->res_coll.atqa; + m_shadow_coll_res.uid = m_tag_information->res_coll.uid; + m_shadow_coll_res.size = &(m_tag_information->res_coll.size); + m_shadow_coll_res.ats = &(m_tag_information->res_coll.ats); + // Finally, a shadow data structure pointer with only reference, no physical shadow, + return &m_shadow_coll_res; +} + +void nfc_tag_ntag_reset_handler() { + // TODO +} + +static int get_information_size_by_tag_type(tag_specific_type_t type) { + return sizeof(nfc_tag_14a_coll_res_entity_t) + sizeof(nfc_tag_ntag_configure_t) + (get_block_max_by_tag_type(type) * NFC_TAG_NTAG_DATA_SIZE); +} + +/** @brief ntag's callback before saving data + * @param type detailed label type + * @param buffer data buffer + * @return to be saved, the length of the data that needs to be saved, it means not saved when 0 + */ +int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer) { + if (m_tag_type != TAG_TYPE_UNKNOWN) { + // Save the corresponding size data according to the current label type + return get_information_size_by_tag_type(type); + } else { + return 0; + } +} + +int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer) { + int info_size = get_information_size_by_tag_type(type); + if (buffer->length >= info_size) { + // Convert the data buffer to NTAG structure type + m_tag_information = (nfc_tag_ntag_information_t *)buffer->buffer; + // The specific type of NTAG that is simulated by the cache + m_tag_type = type; + // Register 14A communication management interface + nfc_tag_14a_handler_t handler_for_14a = { + .get_coll_res = get_ntag_coll_res, + .cb_state = nfc_tag_ntag_state_handler, + .cb_reset = nfc_tag_ntag_reset_handler, + }; + nfc_tag_14a_set_handler(&handler_for_14a); + NRF_LOG_INFO("HF ntag data load finish."); + } else { + NRF_LOG_ERROR("nfc_tag_ntag_information_t too big."); + } + return info_size; +} + +// Initialized NTAG factory data +bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type) { + // default ntag data + uint8_t default_p0[] = { 0x04, 0x68, 0x95, 0x71 }; + uint8_t default_p1[] = { 0xFA, 0x5C, 0x64, 0x80 }; + uint8_t default_p2[] = { 0x42, 0x48, 0x0F, 0xE0 }; + + // default ntag info + nfc_tag_ntag_information_t ntag_tmp_information; + nfc_tag_ntag_information_t *p_ntag_information; + p_ntag_information = &ntag_tmp_information; + int block_max = get_block_max_by_tag_type(tag_type); + for (int block = 0; block < block_max; block++) { + if (block == 0) { + memcpy(p_ntag_information->memory[block], default_p0, NFC_TAG_NTAG_DATA_SIZE); + } + if (block == 1) { + memcpy(p_ntag_information->memory[block], default_p1, NFC_TAG_NTAG_DATA_SIZE); + } + if (block == 2) { + memcpy(p_ntag_information->memory[block], default_p2, NFC_TAG_NTAG_DATA_SIZE); + } + } + + // default ntag auto ant-collision res + p_ntag_information->res_coll.atqa[0] = 0x44; + p_ntag_information->res_coll.atqa[1] = 0x00; + p_ntag_information->res_coll.sak[0] = 0x00; + p_ntag_information->res_coll.uid[0] = 0x04; + p_ntag_information->res_coll.uid[1] = 0x68; + p_ntag_information->res_coll.uid[2] = 0x95; + p_ntag_information->res_coll.uid[3] = 0x71; + p_ntag_information->res_coll.uid[4] = 0xFA; + p_ntag_information->res_coll.uid[5] = 0x5C; + p_ntag_information->res_coll.uid[6] = 0x64; + p_ntag_information->res_coll.size = NFC_TAG_14A_UID_DOUBLE_SIZE; + p_ntag_information->res_coll.ats.length = 0; + + // default ntag config + p_ntag_information->config.mode_uid_magic = true; + p_ntag_information->config.detection_enable = false; + + // save data to flash + tag_sense_type_t sense_type = get_sense_type_from_tag_type(tag_type); + fds_slot_record_map_t map_info; + get_fds_map_by_slot_sense_type_for_dump(slot, sense_type, &map_info); + int info_size = get_information_size_by_tag_type(tag_type); // auto 4 byte align. + NRF_LOG_INFO("NTAG info size: %d", info_size); + bool ret = fds_write_sync(map_info.id, map_info.key, info_size / 4, p_ntag_information); + if (ret) { + NRF_LOG_INFO("Factory slot data success."); + } else { + NRF_LOG_ERROR("Factory slot data error."); + } + return ret; +} diff --git a/firmware/application/src/rfid/nfctag/hf/nfc_ntag.h b/firmware/application/src/rfid/nfctag/hf/nfc_ntag.h index c1e76ce..fcbd430 100644 --- a/firmware/application/src/rfid/nfctag/hf/nfc_ntag.h +++ b/firmware/application/src/rfid/nfctag/hf/nfc_ntag.h @@ -1,39 +1,39 @@ -#ifndef NFC_NTAG_H -#define NFC_NTAG_H - -#include "nfc_14a.h" - -#define NFC_TAG_NTAG_DATA_SIZE 4 -#define NFC_TAG_NTAG_FRAME_SIZE 64 -#define NFC_TAG_NTAG_BLOCK_MAX 231 - -#define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44 -#define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134 -#define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230 - - -typedef struct { - uint8_t mode_uid_magic: 1; - uint8_t detection_enable: 1; - // reserve - uint8_t reserved1: 5; - uint8_t reserved2; - uint8_t reserved3; -} nfc_tag_ntag_configure_t; - -typedef struct __attribute__((aligned(4))) { - nfc_tag_14a_coll_res_entity_t res_coll; - nfc_tag_ntag_configure_t config; - uint8_t memory[NFC_TAG_NTAG_BLOCK_MAX][NFC_TAG_NTAG_DATA_SIZE]; -} -nfc_tag_ntag_information_t; - -typedef struct { - uint8_t tx_buffer[NFC_TAG_NTAG_FRAME_SIZE]; -} nfc_tag_ntag_tx_buffer_t; - -int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer); -int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer); -bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type); - -#endif +#ifndef NFC_NTAG_H +#define NFC_NTAG_H + +#include "nfc_14a.h" + +#define NFC_TAG_NTAG_DATA_SIZE 4 +#define NFC_TAG_NTAG_FRAME_SIZE 64 +#define NFC_TAG_NTAG_BLOCK_MAX 231 + +#define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44 +#define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134 +#define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230 + + +typedef struct { + uint8_t mode_uid_magic: 1; + uint8_t detection_enable: 1; + // reserve + uint8_t reserved1: 5; + uint8_t reserved2; + uint8_t reserved3; +} nfc_tag_ntag_configure_t; + +typedef struct __attribute__((aligned(4))) { + nfc_tag_14a_coll_res_entity_t res_coll; + nfc_tag_ntag_configure_t config; + uint8_t memory[NFC_TAG_NTAG_BLOCK_MAX][NFC_TAG_NTAG_DATA_SIZE]; +} +nfc_tag_ntag_information_t; + +typedef struct { + uint8_t tx_buffer[NFC_TAG_NTAG_FRAME_SIZE]; +} nfc_tag_ntag_tx_buffer_t; + +int nfc_tag_ntag_data_loadcb(tag_specific_type_t type, tag_data_buffer_t *buffer); +int nfc_tag_ntag_data_savecb(tag_specific_type_t type, tag_data_buffer_t *buffer); +bool nfc_tag_ntag_data_factory(uint8_t slot, tag_specific_type_t tag_type); + +#endif diff --git a/resource/dfu_key/warnning.txt b/resource/dfu_key/warning.txt similarity index 100% rename from resource/dfu_key/warnning.txt rename to resource/dfu_key/warning.txt From ef46b22d699f5fd4fe8ea63a0a92bc664522e70a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Aug 2023 13:15:43 +0200 Subject: [PATCH 19/23] Fixed logs corruption and app reset on FDS write, added logs flush on sleep Bug when NRF_LOG_DEFERRED=0 due to a userland NRF_LOG_INFO after FDS record update was initiated, interrupted by FDS record IRQ handler and its own NRF_LOG_INFO resulting in app: Fatal error app: System reset Added a few more NRF_LOG in FDS module as well. Added NRF_LOG_FLUSH in system_off_enter to not miss last messages. --- CHANGELOG.md | 1 + firmware/application/src/app_main.c | 3 +++ firmware/application/src/utils/fds_util.c | 25 +++++++++++++++-------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ba688..d29ccdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fixed logs corruption and app reset on FDS write, added logs flush on sleep (@doegox) - Added support for long-press of buttons (@nemanjan00) - Changed `hw slot delete`, now it can always delete from slot. (@augustozanellato) - Refactor CI pipeline. (@augustozanellato) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 1c0c11f..7ad6795 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -351,6 +351,9 @@ static void system_off_enter(void) { return; }; + // Last call, gate is closing + NRF_LOG_FLUSH(); + // Go to system-off mode (this function will not return; wakeup will cause a reset). // Note that if you insert jlink or drive a Debug, you may report an error when entering the low power consumption. // When starting debugging, we should disable low power consumption state values, or simply not enter low power consumption diff --git a/firmware/application/src/utils/fds_util.c b/firmware/application/src/utils/fds_util.c index af8e1de..bffda22 100644 --- a/firmware/application/src/utils/fds_util.c +++ b/firmware/application/src/utils/fds_util.c @@ -84,16 +84,18 @@ static ret_code_t fds_write_record_nogc(uint16_t id, uint16_t key, uint16_t data }; if (fds_find_record(id, key, &record_desc)) { // Find a record with specified characteristics //If you can find this record, we can perform the update operation + NRF_LOG_INFO("Search FileID: 0x%04x, FileKey: 0x%04x is found, will update.", id, key); err_code = fds_record_update(&record_desc, &record); - if (err_code == NRF_SUCCESS) { - NRF_LOG_INFO("Search FileID: 0x%04x, FileKey: 0x%04x is found, will update.", id, key); - } + if (err_code != NRF_SUCCESS) { + NRF_LOG_INFO("Record update request failed!"); + } // Don't NRF_LOG if request succeeded, it would be interrupted by NRF_LOG in record handler } else { // Unable to find effective records, we will write for the first time + NRF_LOG_INFO("Search FileID: 0x%04x, FileKey: 0x%04x no found, will create.", id, key); err_code = fds_record_write(&record_desc, &record); - if (err_code == NRF_SUCCESS) { - NRF_LOG_INFO("Search FileID: 0x%04x, FileKey: 0x%04x no found, will create.", id, key); - } + if (err_code != NRF_SUCCESS) { + NRF_LOG_INFO("Record creation request failed!"); + } // Don't NRF_LOG if request succeeded, it would be interrupted by NRF_LOG in record handler } return err_code; } @@ -179,6 +181,7 @@ static void fds_evt_handler(fds_evt_t const *p_evt) { if (p_evt->result == NRF_SUCCESS) { NRF_LOG_INFO("NRF52 FDS libraries init success."); } else { + NRF_LOG_INFO("NRF52 FDS libraries init failed"); APP_ERROR_CHECK(p_evt->result); } } @@ -189,9 +192,11 @@ static void fds_evt_handler(fds_evt_t const *p_evt) { NRF_LOG_INFO("Record change: FileID 0x%04x, RecordKey 0x%04x", p_evt->write.file_id, p_evt->write.record_key); if (p_evt->write.file_id == fds_operation_info.id && p_evt->write.record_key == fds_operation_info.key) { // The logic above has ensured that the task we are currently writing is completed! + NRF_LOG_INFO("Record change success"); fds_operation_info.success = true; - } + } else NRF_LOG_INFO("Record change mismatch"); } else { + NRF_LOG_INFO("Record change failed"); APP_ERROR_CHECK(p_evt->result); } } @@ -205,17 +210,21 @@ static void fds_evt_handler(fds_evt_t const *p_evt) { if (p_evt->del.record_id == fds_operation_info.record_id) { // Only check record id because fileID and recordKey aren't available // if deleting via fds_record_iterate. record id is guaranteed to be unique. + NRF_LOG_INFO("Record delete success"); fds_operation_info.success = true; - } + } else NRF_LOG_INFO("Record delete mismatch"); } else { + NRF_LOG_INFO("Record delete failed"); APP_ERROR_CHECK(p_evt->result); } } break; case FDS_EVT_GC: { if (p_evt->result == NRF_SUCCESS) { + NRF_LOG_INFO("FDS gc success"); fds_operation_info.success = true; } else { + NRF_LOG_INFO("FDS gc failed"); APP_ERROR_CHECK(p_evt->result); } } From c24e69b44c227c258158f5d2d392bb20a19ccd2f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Aug 2023 11:14:21 +0200 Subject: [PATCH 20/23] Allow to interrupt sleep sequence during final animation with a simple button press. Because otherwise one must wait for sleep animation to finish, then press button then wait for boot animation to finish... Also, fix saved config CRC after config has been saved --- CHANGELOG.md | 1 + firmware/application/src/app_main.c | 60 ++++++++++++------- .../src/rfid/nfctag/tag_emulation.c | 1 + 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d29ccdd..f544e28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added support for interrupting sleep sequence with a button press during animation (@doegox) - Fixed logs corruption and app reset on FDS write, added logs flush on sleep (@doegox) - Added support for long-press of buttons (@nemanjan00) - Changed `hw slot delete`, now it can always delete from slot. (@augustozanellato) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 7ad6795..a1e9b98 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -53,6 +53,8 @@ static bool m_is_a_btn_press = false; static bool m_is_b_btn_release = false; static bool m_is_a_btn_release = false; +static bool m_system_off_processing = false; + // cpu reset reason static uint32_t m_reset_source; static uint32_t m_gpregret_val; @@ -153,6 +155,12 @@ static void button_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t a * @return None */ static void timer_button_event_handle(void *arg) { + // if button press during shutdown, it's only to wake up quickly + if (m_system_off_processing) { + m_system_off_processing = false; + NRF_LOG_INFO("BUTTON press during shutdown"); + return; + } nrf_drv_gpiote_pin_t pin = *(nrf_drv_gpiote_pin_t *)arg; // Check here if the current GPIO is at the pressed level if (nrf_gpio_pin_read(pin) == 1) { @@ -234,26 +242,10 @@ static void button_init(void) { */ static void system_off_enter(void) { ret_code_t ret; - - // Disable the HF NFC event first - NRF_NFCT->INTENCLR = NRF_NFCT_DISABLE_ALL_INT; - // Then disable the LF LPCOMP event - NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk; - + m_system_off_processing = true; // Save tag data tag_emulation_save(); - // Configure RAM hibernation hold - uint32_t ram8_retention = // RAM8 Each section has 32KB capacity - // POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos ; - // POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos | - // POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos | - // POWER_RAM_POWER_S3RETENTION_On << POWER_RAM_POWER_S3RETENTION_Pos | - // POWER_RAM_POWER_S4RETENTION_On << POWER_RAM_POWER_S4RETENTION_Pos | - POWER_RAM_POWER_S5RETENTION_On << POWER_RAM_POWER_S5RETENTION_Pos; - ret = sd_power_ram_power_set(8, ram8_retention); - APP_ERROR_CHECK(ret); - if (g_is_low_battery_shutdown) { // Don't create too complex animations, just blink LED1 three times. rgb_marquee_stop(); @@ -283,15 +275,39 @@ static void system_off_enter(void) { color = 2; } } - ledblink5(color, slot, dir ? 7 : 0); - ledblink4(color, dir, 7, 99, 75); - ledblink4(color, !dir, 7, 75, 50); - ledblink4(color, dir, 7, 50, 25); - ledblink4(color, !dir, 7, 25, 0); + if (m_system_off_processing) ledblink5(color, slot, dir ? 7 : 0); + if (m_system_off_processing) ledblink4(color, dir, 7, 99, 75); + if (m_system_off_processing) ledblink4(color, !dir, 7, 75, 50); + if (m_system_off_processing) ledblink4(color, dir, 7, 50, 25); + if (m_system_off_processing) ledblink4(color, !dir, 7, 25, 0); } rgb_marquee_stop(); + if (!m_system_off_processing) { + for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { + nrf_gpio_pin_clear(p_led_array[i]); + } + light_up_by_slot(); + sleep_timer_start(SLEEP_DELAY_MS_BUTTON_CLICK); + return; + } } + // Disable the HF NFC event first + NRF_NFCT->INTENCLR = NRF_NFCT_DISABLE_ALL_INT; + // Then disable the LF LPCOMP event + NRF_LPCOMP->INTENCLR = LPCOMP_INTENCLR_CROSS_Msk | LPCOMP_INTENCLR_UP_Msk | LPCOMP_INTENCLR_DOWN_Msk | LPCOMP_INTENCLR_READY_Msk; + + // Configure RAM hibernation hold + uint32_t ram8_retention = // RAM8 Each section has 32KB capacity + // POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos ; + // POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos | + // POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos | + // POWER_RAM_POWER_S3RETENTION_On << POWER_RAM_POWER_S3RETENTION_Pos | + // POWER_RAM_POWER_S4RETENTION_On << POWER_RAM_POWER_S4RETENTION_Pos | + POWER_RAM_POWER_S5RETENTION_On << POWER_RAM_POWER_S5RETENTION_Pos; + ret = sd_power_ram_power_set(8, ram8_retention); + APP_ERROR_CHECK(ret); + // IOs that need to be configured as floating analog inputs ==> no pull-up or pull-down uint32_t gpio_cfg_default_nopull[] = { #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/rfid/nfctag/tag_emulation.c b/firmware/application/src/rfid/nfctag/tag_emulation.c index a036878..93616c3 100644 --- a/firmware/application/src/rfid/nfctag/tag_emulation.c +++ b/firmware/application/src/rfid/nfctag/tag_emulation.c @@ -407,6 +407,7 @@ void tag_emulation_save_config(void) { bool ret = fds_write_sync(FDS_EMULATION_CONFIG_FILE_ID, FDS_EMULATION_CONFIG_RECORD_KEY, sizeof(slotConfig) / 4, (uint8_t *)&slotConfig); if (ret) { NRF_LOG_INFO("Save tag slot config success."); + m_slot_config_crc = new_calc_crc; } else { NRF_LOG_ERROR("Save tag slot config error."); } From 7ff6a0b3a24fcbc069c33418810903e30d7e7db0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Aug 2023 17:56:10 +0200 Subject: [PATCH 21/23] Allow pasting multiple commands at once, as it was with readline --- CHANGELOG.md | 1 + software/script/chameleon_cli_main.py | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f544e28..559abae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added support for pasting several command lines at once with prompt_toolkit (@doegox) - Added support for interrupting sleep sequence with a button press during animation (@doegox) - Fixed logs corruption and app reset on FDS write, added logs flush on sleep (@doegox) - Added support for long-press of buttons (@nemanjan00) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 32b5819..7bb0178 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -97,14 +97,20 @@ class ChameleonCLI: self.print_banner() closing = False + cmd_strs = [] while True: - # wait user input - try: - cmd_str = self.session.prompt(ANSI(self.get_prompt())).strip() - except EOFError: - closing = True - except KeyboardInterrupt: - closing = True + if cmd_strs: + cmd_str = cmd_strs.pop(0) + else: + # wait user input + try: + cmd_str = self.session.prompt(ANSI(self.get_prompt())).strip() + except EOFError: + closing = True + except KeyboardInterrupt: + closing = True + cmd_strs = cmd_str.replace("\r\n", "\n").replace("\r", "\n").split("\n") + cmd_str = cmd_strs.pop(0) if closing or cmd_str in ["exit", "quit", "q", "e"]: print("Bye, thank you. ^.^ ") From 2ba2ca92fd780d332377f945e260501849d7d431 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Aug 2023 19:40:46 +0200 Subject: [PATCH 22/23] More Chinese (auto) translation --- firmware/common/hw_connect.c | 16 ++++++++-------- firmware/common/hw_connect.h | 2 +- .../libraries/bootloader/nrf_bootloader.c | 6 +++--- .../modules/nrfx/drivers/src/nrfx_nfct.c | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/firmware/common/hw_connect.c b/firmware/common/hw_connect.c index 8a3151a..06a24e4 100644 --- a/firmware/common/hw_connect.c +++ b/firmware/common/hw_connect.c @@ -96,11 +96,11 @@ void board_lite_high_voltage_set(void) { void hw_connect_init(void) { #if defined(PROJECT_CHAMELEON_LITE) - board_lite_high_voltage_set(); // lite需要关闭dcdc并且抬高内核电压 + board_lite_high_voltage_set(); // lite needs to turn off dcdc and raise the core voltage #endif - // TODO 请实现此处,实现硬件版本号的读取 - // 测试的时候可以直接改写此版本号 + // TODO: Please implement here to read the hardware version number + // You can directly rewrite this version number when testing m_hw_ver = 1; @@ -210,31 +210,31 @@ uint8_t hw_get_version_code(void) { return m_hw_ver; } -// 初始化设备的LED灯珠 +// Initialize the LED light beads of the device void init_leds(void) { uint32_t *led_pins = hw_get_led_array(); uint32_t *led_rgb_pins = hw_get_rgb_array(); - // 初始化卡槽那几颗LED灯的GPIO(其他的LED由其他的模块控制) + // Initialize the GPIO of the LED lights in the card slot (other LEDs are controlled by other modules) for (uint8_t i = 0; i < RGB_LIST_NUM; i++) { nrf_gpio_cfg_output(led_pins[i]); nrf_gpio_pin_clear(led_pins[i]); } - // 初始化RGB脚 + // Initialize RGB pin for (uint8_t i = 0; i < RGB_CTRL_NUM; i++) { nrf_gpio_cfg_output(led_rgb_pins[i]); nrf_gpio_pin_set(led_rgb_pins[i]); } - // 设置FIELD LED脚为输出且灭掉场灯 + // set FIELD The LED pin is output and the field light is turned off nrf_gpio_cfg_output(LED_FIELD); TAG_FIELD_LED_OFF() } /** * @brief Function for enter tag emulation mode - * @param color: 0 表示r, 1表示g, 2表示b + * @param color: 0 means r, 1 means g, 2 means b */ void set_slot_light_color(uint8_t color) { nrf_gpio_pin_set(LED_R); diff --git a/firmware/common/hw_connect.h b/firmware/common/hw_connect.h index ecc3518..92aa64b 100644 --- a/firmware/common/hw_connect.h +++ b/firmware/common/hw_connect.h @@ -85,7 +85,7 @@ extern uint32_t g_reader_power; #endif -// 通用场灯的操作定义 +// Operational Definitions for General Field Lights #define TAG_FIELD_LED_ON() nrf_gpio_pin_clear(LED_FIELD); #define TAG_FIELD_LED_OFF() nrf_gpio_pin_set(LED_FIELD); diff --git a/firmware/nrf52_sdk/components/libraries/bootloader/nrf_bootloader.c b/firmware/nrf52_sdk/components/libraries/bootloader/nrf_bootloader.c index 38975f3..d6956b2 100644 --- a/firmware/nrf52_sdk/components/libraries/bootloader/nrf_bootloader.c +++ b/firmware/nrf52_sdk/components/libraries/bootloader/nrf_bootloader.c @@ -386,13 +386,13 @@ static bool dfu_enter_check(void) (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 1)) { bool is_usb_attach = false; - // 如果按钮一直是按下的状态,则等待用户释放按钮,期间检测USB插入,如果是插入状态,则进入DFU模式 + // If the button is always pressed, wait for the user to release the button, during which the USB plug-in is detected, and if it is plugged in, enter the DFU mode while (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 1) { is_usb_attach = check_usb_attach(); } NRF_LOG_DEBUG("DFU mode requested via button."); - // 按钮按下,但是USB没插入,则进入普通APP模式, - // 按钮按下,并且USB插入,则进入bootloader模式 + // When the button is pressed, but the USB is not plugged in, it will enter the normal APP mode. + // When the button is pressed and the USB is plugged in, it enters the bootloader mode return is_usb_attach; } diff --git a/firmware/nrf52_sdk/modules/nrfx/drivers/src/nrfx_nfct.c b/firmware/nrf52_sdk/modules/nrfx/drivers/src/nrfx_nfct.c index dfdd416..9c30476 100644 --- a/firmware/nrf52_sdk/modules/nrfx/drivers/src/nrfx_nfct.c +++ b/firmware/nrf52_sdk/modules/nrfx/drivers/src/nrfx_nfct.c @@ -234,11 +234,11 @@ static void nrfx_nfct_field_event_handler(volatile nrfx_nfct_field_state_t field { /* - * 经过思考,既然低功耗读头无法成功唤醒的原因是读头发送太快,而唤醒NFC外设需要时间,恰巧错过了此通信时序。 - * 那我们就需要在首次唤醒NFC模块后,让其留存一段时间,这段时间就是大概能让低功耗读头正常通信的时间。 - * 唤醒NFC模块这段过程是为了让外设和时钟稳定的一个过程,特别是在NRF52840上,那么我们就不能改动唤醒到场侦测事件的这个过程 - * 假设从场丢失事件的回调关闭为切入点,我们可以假装关闭NFC外设(只分发场丢失事件,而不关闭外设),但是实际上留存着事件监听一段时间,假设在这段时间里接收到数据,我们可以立刻将事件转发给观察者 - * 以达到及时处理数据消息的目的,在一段时间内无消息可处理之后,我们可以正式关闭NFC外设,达到节省电量资源的目的。 + * After thinking, since the reason why the low-power reading head cannot be successfully woken up is that the reading head sends too fast, and it takes time to wake up the NFC peripheral, it happened to miss this communication timing. + * Then we need to keep the NFC module for a period of time after waking it up for the first time. This period of time is about the time for the low-power reading head to communicate normally. + * The process of waking up the NFC module is to stabilize the peripherals and the clock, especially on the nRF52840, so we cannot change the process of waking up the presence detection event + * Assuming that the callback from the field loss event is closed as the entry point, we can pretend to turn off the NFC peripheral (only distribute the field loss event, but not close the peripheral), but actually keep the event listening for a period of time, assuming that during this time receivedto the data, we can immediately forward the event to the observer + * In order to achieve the purpose of processing data messages in a timely manner, after there is no message to process for a period of time, we can officially turn off the NFC peripherals to achieve the purpose of saving power resources. */ #if defined(NRF52833_XXAA) || defined(NRF52840_XXAA) nrf_nfct_int_disable(NRFX_NFCT_RX_INT_MASK | NRFX_NFCT_TX_INT_MASK); From 05f25e830c63c4ffbb4927c2cffb55ab84a51a22 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 25 Aug 2023 19:51:27 +0200 Subject: [PATCH 23/23] More Chinese (auto) translation --- software/script/chameleon_cli_unit.py | 20 +++--- software/script/chameleon_cmd.py | 96 +++++++++++++-------------- software/script/chameleon_cstruct.py | 4 +- software/script/chameleon_status.py | 46 ++++++------- software/src/darkside.c | 8 +-- 5 files changed, 87 insertions(+), 87 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index a18690c..97f7fa5 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -391,8 +391,8 @@ class HFMFNested(ReaderRequiredUnit): sea_obj = re.search(r"([a-fA-F0-9]{12})", line) if sea_obj is not None: key_list.append(sea_obj[1]) - # 此处得先去验证一下密码,然后获得验证成功的那个 - # 如果没有验证成功的密码,则说明此次恢复失败了,可以重试一下 + # Here you have to verify the password first, and then get the one that is successfully verified + # If there is no verified password, it means that the recovery failed, you can try again print(f" - [{len(key_list)} candidate keys found ]") for key in key_list: key_bytes = bytearray.fromhex(key) @@ -447,7 +447,7 @@ class HFMFDarkside(ReaderRequiredUnit): def recover_key(self, block_target, type_target): """ - 执行darkside采集与解密 + Execute darkside acquisition and decryption :param block_target: :param type_target: :return: @@ -595,7 +595,7 @@ class HFMFDetectionDecrypt(DeviceRequiredUnit): def decrypt_by_list(self, rs: list): """ - 从侦测日志列表中解密秘钥 + Decrypt key from reconnaissance log list :param rs: :return: """ @@ -1055,8 +1055,8 @@ class HWSlotDataDefault(TagTypeRequiredUnit, SlotIndexRequireUnit): self.add_slot_args(parser) return parser - # m1 1k卡模拟 hw slot init -s 1 -t 3 - # em id卡模拟 hw slot init -s 1 -t 1 + # m1 1k card emulation hw slot init -s 1 -t 3 + # em id card simulation hw slot init -s 1 -t 1 def on_exec(self, args: argparse.Namespace): tag_type = args.type slot_num = args.slot @@ -1117,7 +1117,7 @@ class HWSlotNickSet(SlotIndexRequireUnit, SenseTypeRequireUnit): parser.add_argument('-n', '--name', type=str, required=True, help="Your tag nick name for slot") return parser - # hw slot nick set -s 1 -st 1 -n 测试名称保存 + # hw slot nick set -s 1 -st 1 -n Save the test name def on_exec(self, args: argparse.Namespace): slot_num = args.slot sense_type = args.sense_type @@ -1194,9 +1194,9 @@ class HWDFU(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): print("Application restarting...") self.cmd.enter_dfu_mode() - # 理论上,上面的指令执行完成后,dfu模式会进入,然后USB会重启, - # 我们判断是否成功进入USB,只需要判断USB是否变成DFU设备的VID和PID即可, - # 同时我们记得确认设备的信息,一致时才是同一个设备。 + # In theory, after the above command is executed, the dfu mode will enter, and then the USB will restart, + # To judge whether to enter the USB successfully, we only need to judge whether the USB becomes the VID and PID of the DFU device. + # At the same time, we remember to confirm the information of the device, it is the same device when it is consistent. print(" - Enter success @.@~") # let time for comm thread to send dfu cmd and close port time.sleep(0.1) diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index a3ef8c7..e5da941 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -132,7 +132,7 @@ class TagSenseType(enum.IntEnum): class TagSpecificType(enum.IntEnum): # Empty slot TAG_TYPE_UNKNOWN = 0 - # 125 kHz(ID)cards + # 125 kHz (id) cards TAG_TYPE_EM410X = 1 # Mifare Classic TAG_TYPE_MIFARE_Mini = 2 @@ -322,28 +322,28 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def scan_tag_14a(self): """ - 扫描场内的14a标签 + ( ) 14a tags in the scanning field :return: """ return self.device.send_cmd_sync(DATA_CMD_SCAN_14A_TAG, 0x00) def detect_mf1_support(self): """ - 检测是否是mifare classic标签 + ( ) Detect whether it is mi (ar) classic label :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_SUPPORT_DETECT, 0x00) def detect_mf1_nt_level(self): """ - 检测mifare classic的nt漏洞的等级 + ( ) detect mi (ar) Class of classic nt vulnerabilities :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_NT_LEVEL_DETECT, 0x00) def detect_darkside_support(self): """ - 检测卡片是否易受mifare classic darkside攻击 + ( ) Check if the card is vulnerable to mifare cla (si) darkside attack :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_DETECT, 0x00, None, timeout=20) @@ -351,7 +351,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def detect_nt_distance(self, block_known, type_known, key_known): """ - 检测卡片的随机数距离 + ( ) Detect the random number distance of the card :return: """ data = bytearray() @@ -363,7 +363,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def acquire_nested(self, block_known, type_known, key_known, block_target, type_target): """ - 采集Nested解密需要的关键NT参数 + ( ) Collect the key NT parameters needed for Nested decryption :return: """ data = bytearray() @@ -377,7 +377,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max): """ - 采集Darkside解密需要的关键参数 + ( ) Collect the key parameters needed for Darkside decryption :param block_target: :param type_target: :param first_recover: @@ -399,7 +399,7 @@ class ChameleonCMD: ]) def auth_mf1_key(self, block, type_value, key): """ - 验证mf1秘钥,只验证单个扇区的指定类型的秘钥 + ( ) Verify the mf1 key, only verify the specified type of key for a single sector :param block: :param type_value: :param key: @@ -414,7 +414,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def read_mf1_block(self, block, type_value, key): """ - 读取mf1单块 + ( ) read mf1 monoblock :param block: :param type_value: :param key: @@ -429,7 +429,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def write_mf1_block(self, block, type_value, key, block_data): """ - 写入mf1单块 + ( ) Write mf1 single block :param block: :param type_value: :param key: @@ -446,7 +446,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.LF_TAG_OK) def read_em_410x(self): """ - 读取EM410X的卡号 + ( ) Read the card number of EM410X :return: """ return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00) @@ -454,8 +454,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.LF_TAG_OK) def write_em_410x_to_t55xx(self, id_bytes: bytearray): """ - 写入EM410X卡号到T55XX中 - :param id_bytes: ID卡号 + ( ) Write EM410X card number into T55XX + :param id_by (es) ID card number :return: """ new_key = [0x20, 0x20, 0x66, 0x66] @@ -498,10 +498,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ - 设置当前卡槽的模拟卡的标签类型 - 注意:此操作并不会更改flash中的数据,flash中的数据的变动仅在下次保存时更新 - :param slot_index: 卡槽号码 - :param tag_type: 标签类型 + ( ) Set the label type of the simulated card of the current card slot + ( ) Note: This operation will not change the data in the flash, and the change of the data in the flash will only be updated at the next save + :param slot_in (ex) Card slot number + :param tag_t (pe) label type :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -526,10 +526,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_data_default(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ - 设置指定卡槽的模拟卡的数据为缺省数据 - 注意:此API会将flash中的数据一并进行设置 - :param slot_index: 卡槽号码 - :param tag_type: 要设置的缺省标签类型 + ( ) Set the data of the simulated card in the specified card slot as the default data + ( ) Note: This API will set the data in the flash together + :param slot_in (ex) Card slot number + :param tag_t (pe) The default label type to set :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -541,9 +541,9 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_enable(self, slot_index: SlotNumber, enable: bool): """ - 设置指定的卡槽是否使能 - :param slot_index: 卡槽号码 - :param enable: 是否使能 + ( ) Set whether the specified card slot is enabled + :param slot_in (ex) Card slot number + :param ena (le) Whether to enable :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -555,8 +555,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_em410x_sim_id(self, id_bytes: bytearray): """ - 设置EM410x模拟的卡号 - :param id_bytes: 卡号的字节 + ( ) Set the card number simulated by EM410x + :param id_by (es) byte of the card number :return: """ if len(id_bytes) != 5: @@ -572,8 +572,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_detection_enable(self, enable: bool): """ - 设置是否使能当前卡槽的侦测 - :param enable: 是否使能 + ( ) Set whether to enable the detection of the current card slot + :param ena (le) Whether to enable :return: """ data = bytearray() @@ -582,7 +582,7 @@ class ChameleonCMD: def get_mf1_detection_count(self): """ - 获取当前侦测记录的统计个数 + ( ) Get the statistics of the current detection records :return: """ return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00) @@ -590,8 +590,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def get_mf1_detection_log(self, index: int): """ - 从指定的index位置开始获取侦测日志 - :param index: 开始索引 + ( ) Get detection logs from the specified index position + :param in (ex) start index :return: """ data = bytearray() @@ -601,9 +601,9 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_block_data(self, block_start: int, block_data: bytearray): """ - 设置MF1的模拟卡的块数据 - :param block_start: 开始设置块数据的位置,包含此位置 - :param block_data: 要设置的块数据的字节缓冲区,可包含多个块数据,自动从 block_start 递增 + ( ) Set the block data of the analog card of MF1 + :param block_st (rt) Start setting the location of block data, including this location + :param block_d (ta) The byte buffer of the block data to be set can contain multiple block data, automatically from block_s (ar) increment :return: """ data = bytearray() @@ -621,10 +621,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray): """ - 设置MF1的模拟卡的防冲撞资源信息 - :param sak: sak字节 - :param atqa: atqa数组 - :param uid: 卡号数组 + ( ) Set the anti-collision resource information of the MF1 analog card + :param (ak) sak bytes + :param a (qa) atqa array + :param (id) card number array :return: """ data = bytearray() @@ -636,10 +636,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType, name: bytes): """ - 设置MF1的模拟卡的防冲撞资源信息 - :param slot: 卡槽号码 - :param sense_type: 场类型 - :param name: 卡槽昵称 + ( ) Set the anti-collision resource information of the MF1 analog card + :param s (ot) Card slot number + :param sense_t (pe) field type + :param n (me) Card slot nickname :return: """ # SlotNumber() will raise error for us if slot not in slot range @@ -651,9 +651,9 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def get_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType): """ - 设置MF1的模拟卡的防冲撞资源信息 - :param slot: 卡槽号码 - :param sense_type: 场类型 + ( ) Set the anti-collision resource information of the MF1 analog card + :param s (ot) Card slot number + :param sense_t (pe) field type :return: """ # SlotNumber() will raise error for us if slot not in slot range @@ -699,14 +699,14 @@ class ChameleonCMD: def update_slot_data_config(self): """ - 更新卡槽的配置和数据到flash中。 + ( ) Update the configuration and data of the card slot to flash. :return: """ return self.device.send_cmd_sync(DATA_CMD_SLOT_DATA_CONFIG_SAVE, 0x00) def enter_dfu_mode(self): """ - 重启进入DFU模式(bootloader) + ( ) Reboot into DFU mode (bootloader) :return: """ return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True) diff --git a/software/script/chameleon_cstruct.py b/software/script/chameleon_cstruct.py index 519cdc8..76844f3 100644 --- a/software/script/chameleon_cstruct.py +++ b/software/script/chameleon_cstruct.py @@ -77,7 +77,7 @@ def parse_mf1_detection_result(data: bytearray): :param data: data :return: """ - # 转换 + # convert result_list = [] pos = 0 while pos < len(data): @@ -92,7 +92,7 @@ def parse_mf1_detection_result(data: bytearray): }) pos += 18 - # 归类 + # classify result_map = {} for item in result_list: uid = item['uid'] diff --git a/software/script/chameleon_status.py b/software/script/chameleon_status.py index 63c8579..3ae4f0f 100644 --- a/software/script/chameleon_status.py +++ b/software/script/chameleon_status.py @@ -14,32 +14,32 @@ class MetaDevice(type): class Device(metaclass=MetaDevice): - HF_TAG_OK = 0x00 # IC卡操作成功 - HF_TAG_NO = 0x01 # 没有发现IC卡 - HF_ERRSTAT = 0x02 # IC卡通信异常 - HF_ERRCRC = 0x03 # IC卡通信校验异常 - HF_COLLISION = 0x04 # IC卡冲突 - HF_ERRBCC = 0x05 # IC卡BCC错误 - MF_ERRAUTH = 0x06 # MF卡验证失败 - HF_ERRPARITY = 0x07 # IC卡奇偶校验错误 + HF_TAG_OK = 0x00 # IC card operation is successful + HF_TAG_NO = 0x01 # IC card not found + HF_ERRSTAT = 0x02 # Abnormal IC card communication + HF_ERRCRC = 0x03 # IC card communication verification abnormal + HF_COLLISION = 0x04 # IC card conflict + HF_ERRBCC = 0x05 # IC card BCC error + MF_ERRAUTH = 0x06 # MF card verification failed + HF_ERRPARITY = 0x07 # IC card parity error - DARKSIDE_CANT_FIXED_NT = 0x20 # Darkside,无法固定随机数,这个情况可能出现在UID卡上 - DARKSIDE_LUCK_AUTH_OK = 0x21 # Darkside,直接验证成功了,可能刚好密钥是空的 - DARKSIDE_NACK_NO_SEND = 0x22 # Darkside,卡片不响应nack,可能是一张修复了nack逻辑漏洞的卡片 - DARKSIDE_TAG_CHANGED = 0x23 # Darkside,在运行darkside的过程中出现了卡片切换,可能信号问题,或者真的是两张卡迅速切换了 - NESTED_TAG_IS_STATIC = 0x24 # Nested,检测到卡片应答的随机数是固定的 - NESTED_TAG_IS_HARD = 0x25 # Nested,检测到卡片应答的随机数是不可预测的 + DARKSIDE_CANT_FIXED_NT = 0x20 # Darkside, the random number cannot be fixed, this situation may appear on the UID card + DARKSIDE_LUCK_AUTH_OK = 0x21 # Darkside, the direct verification is successful, maybe the key is empty + DARKSIDE_NACK_NO_SEND = 0x22 # Darkside, the card doesn't respond to nack, probably a card that fixes the nack logic bug + DARKSIDE_TAG_CHANGED = 0x23 # Darkside, there is a card switching during the running of darkside, maybe there is a signal problem, or the two cards really switched quickly + NESTED_TAG_IS_STATIC = 0x24 # Nested, it is detected that the random number of the card response is fixed + NESTED_TAG_IS_HARD = 0x25 # Nested, detected nonce for card response is unpredictable - LF_TAG_OK = 0x40 # 低频卡的一些操作成功! - EM410X_TAG_NO_FOUND = 0x41 # 无法搜索到有效的EM410X标签 + LF_TAG_OK = 0x40 # Some operations with low frequency cards succeeded! + EM410X_TAG_NO_FOUND = 0x41 # Unable to search for a valid EM410X label - STATUS_PAR_ERR = 0x60 # BLE指令传递的参数错误,或者是调用某些函数传递的参数错误 - STATUS_DEVICE_MODE_ERROR = 0x66 # 当前设备所处的模式错误,无法调用对应的API - STATUS_INVALID_CMD = 0x67 # 无效的指令 - STATUS_DEVICE_SUCCESS = 0x68 # 设备相关操作成功执行 - STATUS_NOT_IMPLEMENTED = 0x69 # 调用了某些未实现的操作,属于开发者遗漏的错误 - STATUS_FLASH_WRITE_FAIL = 0x70 # flash写入失败 - STATUS_FLASH_READ_FAIL = 0x71 # flash读取失败 + STATUS_PAR_ERR = 0x60 # The parameters passed by the BLE instruction are wrong, or the parameters passed by calling some functions are wrong + STATUS_DEVICE_MODE_ERROR = 0x66 # The mode of the current device is wrong, and the corresponding API cannot be called + STATUS_INVALID_CMD = 0x67 # invalid command + STATUS_DEVICE_SUCCESS = 0x68 # Device-related operations performed successfully + STATUS_NOT_IMPLEMENTED = 0x69 # Some unimplemented operations were called, an error missed by the developer + STATUS_FLASH_WRITE_FAIL = 0x70 # flash write failed + STATUS_FLASH_READ_FAIL = 0x71 # flash read failed message = { diff --git a/software/src/darkside.c b/software/src/darkside.c index 21cdc11..b828cc6 100644 --- a/software/src/darkside.c +++ b/software/src/darkside.c @@ -17,7 +17,7 @@ typedef struct { uint64_t ks_list; } DarksideParam; -// 转换字符串为U32类型 +// Convert string to U32 type uint64_t atoui(const char *str) { uint64_t result = 0; @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) { printf("Unexcepted param count\n"); return EXIT_FAILURE; } - // 初始化UID + // Initialize UID uint32_t uid = (uint32_t)atoui(argv[1]); uint32_t count = 0, i = 0; uint32_t keycount = 0; @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) { } for (i = 0; i < count; i++) { - // 初始化NT, NR, AR + // Initialize NT, NR, AR uint32_t nt = dps[i].nt; uint32_t nr = dps[i].nr; uint32_t ar = dps[i].ar; @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) { printf("AR = %"PRIu32"\r\n", ar); */ - // 开始解密 + // start decrypting keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); if (keycount == 0) {