diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index ade7f54..d4f42e1 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -141,7 +141,7 @@ static data_frame_tx_t *cmd_processor_reset_settings(uint16_t cmd, uint16_t stat } static data_frame_tx_t *cmd_processor_get_device_settings(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { - uint8_t settings[7 + BLE_PAIRING_KEY_LEN] = {}; + uint8_t settings[8 + BLE_PAIRING_KEY_LEN] = {}; settings[0] = SETTINGS_CURRENT_VERSION; // current version settings[1] = settings_get_animation_config(); // animation mode settings[2] = settings_get_button_press_config('A'); // short A button press mode @@ -150,7 +150,8 @@ static data_frame_tx_t *cmd_processor_get_device_settings(uint16_t cmd, uint16_t settings[5] = settings_get_long_button_press_config('B'); // long B button press mode settings[6] = settings_get_ble_pairing_enable(); // is device require pairing memcpy(settings + 7, settings_get_ble_connect_key(), BLE_PAIRING_KEY_LEN); - return data_frame_make(cmd, STATUS_SUCCESS, 7 + BLE_PAIRING_KEY_LEN, settings); + settings[7 + BLE_PAIRING_KEY_LEN] = settings_get_sleep_timeout() / 1000U; // wake timeout in seconds + return data_frame_make(cmd, STATUS_SUCCESS, 8 + BLE_PAIRING_KEY_LEN, settings); } static data_frame_tx_t *cmd_processor_set_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { @@ -208,6 +209,19 @@ static data_frame_tx_t *cmd_processor_set_long_button_press_config(uint16_t cmd, return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL); } +static data_frame_tx_t *cmd_processor_get_sleep_timeout(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + uint8_t seconds = settings_get_sleep_timeout() / 1000U; + return data_frame_make(cmd, STATUS_SUCCESS, 1, &seconds); +} + +static data_frame_tx_t *cmd_processor_set_sleep_timeout(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + if (length != 1 || data[0] < SETTINGS_SLEEP_TIMEOUT_MIN_S || data[0] > SETTINGS_SLEEP_TIMEOUT_MAX_S) { + return data_frame_make(cmd, STATUS_PAR_ERR, 0, NULL); + } + settings_set_sleep_timeout(data[0]); + return data_frame_make(cmd, STATUS_SUCCESS, 0, NULL); +} + static data_frame_tx_t *cmd_processor_get_ble_pairing_enable(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { uint8_t is_enable = settings_get_ble_pairing_enable(); return data_frame_make(cmd, STATUS_SUCCESS, 1, &is_enable); @@ -2613,6 +2627,8 @@ static cmd_data_map_t m_data_cmd_map[] = { { DATA_CMD_GET_DEVICE_CAPABILITIES, NULL, cmd_processor_get_device_capabilities, NULL }, { DATA_CMD_GET_BLE_PAIRING_ENABLE, NULL, cmd_processor_get_ble_pairing_enable, NULL }, { DATA_CMD_SET_BLE_PAIRING_ENABLE, NULL, cmd_processor_set_ble_pairing_enable, NULL }, + { DATA_CMD_GET_SLEEP_TIMEOUT, NULL, cmd_processor_get_sleep_timeout, NULL }, + { DATA_CMD_SET_SLEEP_TIMEOUT, NULL, cmd_processor_set_sleep_timeout, NULL }, { DATA_CMD_GET_ALL_SLOT_NICKS, NULL, cmd_processor_get_all_slot_nicks, NULL }, #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index ea596cf..1ad6dfb 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -479,7 +479,7 @@ static void check_wakeup_src(void) { light_up_by_slot(); // If no operation follows, wait for the timeout and then deep hibernate - sleep_timer_start(SLEEP_DELAY_MS_BUTTON_WAKEUP); + sleep_timer_start(settings_get_sleep_timeout()); } else if ((m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) || (m_gpregret_val & RESET_ON_LF_FIELD_EXISTS_Msk)) { NRF_LOG_INFO("WakeUp from rfid field"); diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index f9f00c6..22ae409 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -46,6 +46,8 @@ #define DATA_CMD_GET_BLE_PAIRING_ENABLE (1036) #define DATA_CMD_SET_BLE_PAIRING_ENABLE (1037) #define DATA_CMD_GET_ALL_SLOT_NICKS (1038) +#define DATA_CMD_GET_SLEEP_TIMEOUT (1039) +#define DATA_CMD_SET_SLEEP_TIMEOUT (1040) // // ****************************************************************** diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 738e7ac..fba0db2 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -53,6 +53,11 @@ void settings_init_ble_pairing_enable_config(void) { config.ble_pairing_enable = false; } +// add on version6 +void settings_init_sleep_timeout_config(void) { + config.sleep_timeout = SETTINGS_SLEEP_TIMEOUT_DEFAULT_S; +} + void settings_init_config(void) { settings_update_version_for_config(); config.animation_config = SettingsAnimationModeFull; // add on version1 @@ -60,6 +65,7 @@ void settings_init_config(void) { settings_init_button_long_press_config(); settings_init_ble_connect_key_config(); settings_init_ble_pairing_enable_config(); + settings_init_sleep_timeout_config(); } void settings_migrate(void) { @@ -80,6 +86,9 @@ void settings_migrate(void) { case 4: settings_init_ble_pairing_enable_config(); + case 5: + settings_init_sleep_timeout_config(); + /* * 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 @@ -291,3 +300,11 @@ bool settings_get_ble_pairing_enable(void) { bool settings_get_ble_pairing_enable_first_load(void) { return m_ble_pairing_enable_first_load_value; } + +uint32_t settings_get_sleep_timeout(void) { + return config.sleep_timeout * 1000U; +} + +void settings_set_sleep_timeout(uint8_t seconds) { + config.sleep_timeout = seconds; +} diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index cd8baf3..73f6a5d 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -5,7 +5,10 @@ #include "utils.h" -#define SETTINGS_CURRENT_VERSION 5 +#define SETTINGS_CURRENT_VERSION 6 +#define SETTINGS_SLEEP_TIMEOUT_DEFAULT_S 8 // default wake timeout in seconds (matches SLEEP_DELAY_MS_BUTTON_WAKEUP) +#define SETTINGS_SLEEP_TIMEOUT_MIN_S 5 +#define SETTINGS_SLEEP_TIMEOUT_MAX_S 60 #define BLE_PAIRING_KEY_LEN 6 #define DEFAULT_BLE_PAIRING_KEY "123456" // length must == 6 @@ -51,8 +54,8 @@ typedef struct ALIGN_U32 { // 6 byte uint8_t ble_connect_key[6]; - // 1 byte - uint8_t reserved1; // see bottom. + // 1 byte (add on version6) + uint8_t sleep_timeout; // wake timeout in seconds after button wakeup /* * Warning !!!!!!!!!!!!!!!!!!!!!! <------------- @@ -78,4 +81,7 @@ void settings_set_ble_connect_key(uint8_t *key); void settings_set_ble_pairing_enable(bool enable); bool settings_get_ble_pairing_enable(void); bool settings_get_ble_pairing_enable_first_load(void); +uint32_t settings_get_sleep_timeout(void); +void settings_set_sleep_timeout(uint8_t seconds); +void settings_init_sleep_timeout_config(void); #endif \ No newline at end of file diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4fc499d..ac1a5e1 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -426,7 +426,7 @@ class MFUAuthArgsUnit(ReaderRequiredUnit): def key_parser(key: str) -> bytes: try: key = bytes.fromhex(key) - except: + except ValueError: raise ValueError("Key should be a hex string") if len(key) not in [4, 16]: @@ -5826,7 +5826,6 @@ class LFIOProxWriteT55xx(LFIOProxIdArgsUnit, ReaderRequiredUnit): cn & 0xFFFF, raw8 ) - result = self.cmd.ioprox_write_to_t55xx(payload16) print(f"ioProx XSF format") @@ -6304,7 +6303,7 @@ class LFADCGenericRead(ReaderRequiredUnit): avg += val print(f"avg: {hex(round(avg / len(resp)))}") else: - print(f"generic read error") + print("generic read error") @hw_slot.command("list") @@ -6807,6 +6806,40 @@ class HWSettingsAnimation(DeviceRequiredUnit): print(AnimationMode(self.cmd.get_animation_mode())) +@hw_settings.command("sleeptimeout") +class HWSettingsSleepTimeout(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit: + parser = ArgumentParserNoExit() + parser.description = "Get or set the wake timeout after a button press (5-60 seconds)" + parser.add_argument( + "-s", + "--seconds", + type=int, + required=False, + help="Wake timeout in seconds (5-60)", + metavar="SECONDS", + ) + return parser + + def on_exec(self, args: argparse.Namespace): + if args.seconds is not None: + seconds = args.seconds + if seconds < 5: + print(color_string((CR, "Error: value is too low. Please enter a value between 5 and 60 seconds."))) + return + if seconds > 60: + print(color_string((CR, "Error: value is too high. Please enter a value between 5 and 60 seconds."))) + return + if seconds >= 30: + print(color_string((CY, "Warning: a long wake timeout will drain the battery faster."))) + self.cmd.set_sleep_timeout(seconds) + print(f"Wake timeout set to {seconds} seconds.") + print(color_string((CY, "Do not forget to store your settings in flash!"))) + else: + current = self.cmd.get_sleep_timeout() + print(f"Current wake timeout: {current} seconds") + + @hw_settings.command("bleclearbonds") class HWSettingsBleClearBonds(DeviceRequiredUnit): diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index a59bdea..d28fd43 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -8,7 +8,7 @@ from chameleon_enum import Command, SlotNumber, Status, TagSenseType, TagSpecifi from chameleon_enum import ButtonPressFunction, ButtonType, MifareClassicDarksideStatus from chameleon_enum import MfcKeyType, MfcValueBlockOperator -CURRENT_VERSION_SETTINGS = 5 +CURRENT_VERSION_SETTINGS = 6 new_key = b'\x20\x20\x66\x66' old_keys = [b'\x51\x24\x36\x48', b'\x19\x92\x04\x27'] @@ -1402,6 +1402,24 @@ class ChameleonCMD: data = struct.pack('!B', value) return self.device.send_cmd_sync(Command.SET_ANIMATION_MODE, data) + @expect_response(Status.SUCCESS) + def get_sleep_timeout(self): + """ + Get the wake timeout (in seconds) after a button wakeup + """ + resp = self.device.send_cmd_sync(Command.GET_SLEEP_TIMEOUT) + if resp.status == Status.SUCCESS: + resp.parsed = struct.unpack('!B', resp.data)[0] + return resp + + @expect_response(Status.SUCCESS) + def set_sleep_timeout(self, seconds: int): + """ + Set the wake timeout (in seconds) after a button wakeup + """ + data = struct.pack('!B', seconds) + return self.device.send_cmd_sync(Command.SET_SLEEP_TIMEOUT, data) + @expect_response(Status.SUCCESS) def reset_settings(self): """ @@ -1541,7 +1559,7 @@ class ChameleonCMD: def get_device_settings(self): """ Get all possible settings - For version 5: + For version 6: settings[0] = SETTINGS_CURRENT_VERSION; // current version settings[1] = settings_get_animation_config(); // animation mode settings[2] = settings_get_button_press_config('A'); // short A button press mode @@ -1550,6 +1568,7 @@ class ChameleonCMD: settings[5] = settings_get_long_button_press_config('B'); // long B button press mode settings[6] = settings_get_ble_pairing_enable(); // does device require pairing settings[7:13] = settings_get_ble_pairing_key(); // BLE pairing key + settings[13] = sleep_timeout in seconds; // wake timeout after button wakeup """ resp = self.device.send_cmd_sync(Command.GET_DEVICE_SETTINGS) if resp.status == Status.SUCCESS: @@ -1560,8 +1579,8 @@ class ChameleonCMD: raise ValueError("Settings version in app newer than Chameleon. " "Please upgrade Chameleon firmware") settings_version, animation_mode, btn_press_A, btn_press_B, btn_long_press_A, \ - btn_long_press_B, ble_pairing_enable, ble_pairing_key = \ - struct.unpack('!BBBBBBB6s', resp.data) + btn_long_press_B, ble_pairing_enable, ble_pairing_key, sleep_timeout = \ + struct.unpack('!BBBBBBB6sB', resp.data) resp.parsed = {'settings_version': settings_version, 'animation_mode': animation_mode, 'btn_press_A': btn_press_A, @@ -1569,7 +1588,8 @@ class ChameleonCMD: 'btn_long_press_A': btn_long_press_A, 'btn_long_press_B': btn_long_press_B, 'ble_pairing_enable': ble_pairing_enable, - 'ble_pairing_key': ble_pairing_key} + 'ble_pairing_key': ble_pairing_key, + 'sleep_timeout': sleep_timeout} return resp @expect_response(Status.SUCCESS) diff --git a/software/script/chameleon_enum.py b/software/script/chameleon_enum.py index c402d52..05bf75f 100644 --- a/software/script/chameleon_enum.py +++ b/software/script/chameleon_enum.py @@ -57,6 +57,9 @@ class Command(enum.IntEnum): GET_BLE_PAIRING_ENABLE = 1036 SET_BLE_PAIRING_ENABLE = 1037 + GET_SLEEP_TIMEOUT = 1039 + SET_SLEEP_TIMEOUT = 1040 + HF14A_SCAN = 2000 MF1_DETECT_SUPPORT = 2001 MF1_DETECT_PRNG = 2002