diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fcf963..d3cedbc 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 `hf settings blepair` command to get and set ble pairing enable state, and default disable ble pair. (@xianglin1998) - Added `hf mf info` command to get UID/SAK/ATQA from slot (@Foxushka) - Added `hw raw` to send raw command to Chameleon (@Foxushka) - Added command to fetch all available commands from Chameleon and test if Chameleon supports it (@Foxushka) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 44f21ce..fa2d1f9 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -129,7 +129,6 @@ data_frame_tx_t *cmd_processor_get_settings(uint16_t cmd, uint16_t status, uint1 return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 6 + BLE_CONNECT_KEY_LEN_MAX, settings); } - data_frame_tx_t *cmd_processor_set_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { if (length == 1) { status = STATUS_DEVICE_SUCCESS; @@ -200,6 +199,21 @@ data_frame_tx_t *cmd_processor_set_long_button_press_config(uint16_t cmd, uint16 return data_frame_make(cmd, status, 0, NULL); } +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_DEVICE_SUCCESS, 1, (uint8_t *)(&is_enable)); +} + +data_frame_tx_t *cmd_processor_set_ble_pairing_enable(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { + if (length == 1 && (data[0] == true || data[0] == false)) { + settings_set_ble_pairing_enable(data[0]); + status = STATUS_DEVICE_SUCCESS; + } else { + 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) { @@ -781,11 +795,11 @@ data_frame_tx_t *cmd_processor_get_enabled_slots(uint16_t cmd, uint16_t status, data_frame_tx_t *cmd_processor_get_ble_connect_key(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { return data_frame_make( - cmd, - STATUS_DEVICE_SUCCESS, - BLE_CONNECT_KEY_LEN_MAX, // 6 - settings_get_ble_connect_key() // Get key point from config - ); + cmd, + STATUS_DEVICE_SUCCESS, + BLE_CONNECT_KEY_LEN_MAX, // 6 + settings_get_ble_connect_key() // Get key point from config + ); } data_frame_tx_t *cmd_processor_set_ble_connect_key(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { @@ -801,10 +815,6 @@ data_frame_tx_t *cmd_processor_set_ble_connect_key(uint16_t cmd, uint16_t status if (is_valid_key) { // Key is valid, we can update to config settings_set_ble_connect_key(data); - advertising_stop(); - set_ble_connect_key(settings_get_ble_connect_key()); - // clear bond if exists - advertising_start(true); status = STATUS_DEVICE_SUCCESS; } else { status = STATUS_PAR_ERR; @@ -889,6 +899,8 @@ static cmd_data_map_t m_data_cmd_map[] = { { DATA_CMD_GET_DEVICE, NULL, cmd_processor_get_device, NULL }, { DATA_CMD_GET_SETTINGS, NULL, cmd_processor_get_settings, NULL }, { DATA_CMD_GET_DEVICE_CAPABILITIES, NULL, NULL, 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 }, #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 4282db5..030cd38 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -500,7 +500,7 @@ static void check_wakeup_src(void) { if (nrfx_power_usbstatus_get() != NRFX_POWER_USB_STATE_DISCONNECTED) { NRF_LOG_INFO("USB Power found."); // usb plugged in can broadcast BLE at will - advertising_start(true); + advertising_start(false); } else { sleep_timer_start(SLEEP_DELAY_MS_FIRST_POWER); // Wait a while and go straight to hibernation, do nothing } @@ -754,13 +754,17 @@ static void blink_usb_led_status(void) { } static void lesc_event_process(void) { - ret_code_t err_code; - err_code = nrf_ble_lesc_request_handler(); - APP_ERROR_CHECK(err_code); + if (settings_get_ble_pairing_enable_first_load()) { + ret_code_t err_code; + err_code = nrf_ble_lesc_request_handler(); + APP_ERROR_CHECK(err_code); + } } static void ble_passkey_init(void) { - set_ble_connect_key(settings_get_ble_connect_key()); + if (settings_get_ble_pairing_enable_first_load()) { + set_ble_connect_key(settings_get_ble_connect_key()); + } } /**@brief Application main function. @@ -769,6 +773,9 @@ int main(void) { hw_connect_init(); // Remember to initialize the pins first cmd_map_init(); // Set function in CMD map for DATA_CMD_GET_DEVICE_CAPABILITIES + fds_util_init(); // Initialize fds tool + settings_load_config(); // Load settings from flash + init_leds(); // LED initialization log_init(); // Log initialization gpio_te_init(); // Initialize GPIO matrix library @@ -782,12 +789,10 @@ int main(void) { bsp_timer_start(); // Start BSP TIMER and prepare it for processing business logic button_init(); // Button initialization for handling business logic sleep_timer_init(); // Soft timer initialization for hibernation - fds_util_init(); // Initialize fds tool package tag_emulation_init(); // Analog card initialization rgb_marquee_init(); // Light effect initialization - settings_load_config(); // Load settings from flash - ble_passkey_init(); // after settings loaded, we can init ble connect key. + ble_passkey_init(); // init ble connect key. // cmd callback register on_data_frame_complete(on_data_frame_received); diff --git a/firmware/application/src/ble_main.c b/firmware/application/src/ble_main.c index 112d277..577a93e 100644 --- a/firmware/application/src/ble_main.c +++ b/firmware/application/src/ble_main.c @@ -322,10 +322,16 @@ static void services_init(void) { bas_init_obj.p_report_ref = NULL; bas_init_obj.initial_batt_level = 100; - bas_init_obj.bl_rd_sec = SEC_MITM; - bas_init_obj.bl_cccd_wr_sec = SEC_MITM; - bas_init_obj.bl_report_rd_sec = SEC_MITM; - + if (settings_get_ble_pairing_enable_first_load()) { + bas_init_obj.bl_rd_sec = SEC_MITM; + bas_init_obj.bl_cccd_wr_sec = SEC_MITM; + bas_init_obj.bl_report_rd_sec = SEC_MITM; + } else { + bas_init_obj.bl_rd_sec = SEC_OPEN; + bas_init_obj.bl_cccd_wr_sec = SEC_OPEN; + bas_init_obj.bl_report_rd_sec = SEC_OPEN; + } + err_code = ble_bas_init(&m_bas, &bas_init_obj); APP_ERROR_CHECK(err_code); } @@ -439,8 +445,13 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported? No, is supported now, hahahaha... - // err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - // APP_ERROR_CHECK(err_code); + // But... the pairing is enable? + if (settings_get_ble_pairing_enable_first_load()) { + NRF_LOG_DEBUG("Pairing is enable, The BLE_GAP_EVT_SEC_PARAMS_REQUEST event is handled by the pairing manager."); + } else { + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); + APP_ERROR_CHECK(err_code); + } break; case BLE_GAP_EVT_PASSKEY_DISPLAY: { @@ -585,12 +596,14 @@ static void whitelist_set(pm_peer_id_list_skip_t skip) { /**@brief Function for starting advertising. */ void advertising_start(bool erase_bonds) { - if (erase_bonds == true) { - delete_bonds_all(); + if (erase_bonds == true && settings_get_ble_pairing_enable_first_load()) { // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. + // So we don't call `ble_advertising_start()` after `delete_bonds_all()`. + delete_bonds_all(); } else { - whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); - + if (settings_get_ble_pairing_enable_first_load()) { + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + } ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); APP_ERROR_CHECK(ret); } @@ -770,5 +783,9 @@ void ble_slave_init(void) { services_init(); // Initialization of service characteristics advertising_init(); // Broadcast parameter initialization conn_params_init(); // Connection parameter initialization - peer_manager_init(); // Peer manager Initialization + + // Pairing enable? + if (settings_get_ble_pairing_enable_first_load()) { + peer_manager_init(); // Peer manager Initialization + } } diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 3d6976c..f859501 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -41,7 +41,8 @@ #define DATA_CMD_GET_DEVICE (1033) #define DATA_CMD_GET_SETTINGS (1034) #define DATA_CMD_GET_DEVICE_CAPABILITIES (1035) - +#define DATA_CMD_GET_BLE_PAIRING_ENABLE (1036) +#define DATA_CMD_SET_BLE_PAIRING_ENABLE (1037) // // ****************************************************************** diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 0c02363..ddf72d9 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -11,9 +11,10 @@ #include "nrf_log_default_backends.h" NRF_LOG_MODULE_REGISTER(); -static settings_data_t config; +static settings_data_t config; static uint16_t m_config_crc; +static bool m_ble_pairing_enable_first_load_value; static void update_config_crc(void) { calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&m_config_crc); @@ -47,13 +48,18 @@ void settings_init_ble_connect_key_config(void) { settings_set_ble_connect_key(p_key_u8); } +// add on version5 +void settings_init_ble_pairing_enable_config(void) { + config.ble_pairing_enable = false; +} + void settings_init_config(void) { settings_update_version_for_config(); - // add on version1 - config.animation_config = SettingsAnimationModeFull; + config.animation_config = SettingsAnimationModeFull; // add on version1 settings_init_button_press_config(); settings_init_button_long_press_config(); settings_init_ble_connect_key_config(); + settings_init_ble_pairing_enable_config(); } void settings_migrate(void) { @@ -71,6 +77,9 @@ void settings_migrate(void) { case 3: settings_init_ble_connect_key_config(); + case 4: + settings_init_ble_pairing_enable_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 @@ -106,6 +115,9 @@ void settings_load_config(void) { if (config_did_change()) { settings_save_config(); } + + // Assign values only after the first configuration load. + m_ble_pairing_enable_first_load_value = config.ble_pairing_enable; } uint8_t settings_save_config(void) { @@ -266,3 +278,15 @@ uint8_t *settings_get_ble_connect_key(void) { void settings_set_ble_connect_key(uint8_t *key) { memcpy(config.ble_connect_key, key, BLE_CONNECT_KEY_LEN_MAX); } + +void settings_set_ble_pairing_enable(bool enable) { + config.ble_pairing_enable = enable; +} + +bool settings_get_ble_pairing_enable(void) { + return config.ble_pairing_enable; +} + +bool settings_get_ble_pairing_enable_first_load(void) { + return m_ble_pairing_enable_first_load_value; +} diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index cdc5f62..1a26bf1 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -5,7 +5,7 @@ #include "utils.h" -#define SETTINGS_CURRENT_VERSION 4 +#define SETTINGS_CURRENT_VERSION 5 #define BLE_CONNECT_KEY_LEN_MAX 6 #define DEFAULT_BLE_CONNECT_KEY "123456" // length must == 6 @@ -32,7 +32,8 @@ typedef struct ALIGN_U32 { // 1 byte uint8_t animation_config : 2; - uint8_t reserved0 : 6; // If you are add switch field, reallocating me. + uint8_t ble_pairing_enable : 1; + uint8_t reserved0 : 5; // If you are add switch field, reallocating me. // 1 byte uint8_t button_a_press : 4; @@ -69,4 +70,7 @@ void settings_set_long_button_press_config(char which, uint8_t value); bool is_settings_button_type_valid(char type); uint8_t *settings_get_ble_connect_key(void); 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); #endif diff --git a/firmware/nrf52_sdk/components/ble/ble_services/ble_nus/ble_nus.c b/firmware/nrf52_sdk/components/ble/ble_services/ble_nus/ble_nus.c index e9d5404..d67505b 100644 --- a/firmware/nrf52_sdk/components/ble/ble_services/ble_nus/ble_nus.c +++ b/firmware/nrf52_sdk/components/ble/ble_services/ble_nus/ble_nus.c @@ -42,6 +42,7 @@ #include "ble.h" #include "ble_nus.h" #include "ble_srv_common.h" +#include "settings.h" #define NRF_LOG_MODULE_NAME ble_nus #if BLE_NUS_CONFIG_LOG_ENABLED @@ -283,10 +284,13 @@ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) add_char_params.char_props.write = 1; add_char_params.char_props.write_wo_resp = 1; - // add_char_params.read_access = SEC_OPEN; - // add_char_params.write_access = SEC_OPEN; - add_char_params.read_access = SEC_MITM; - add_char_params.write_access = SEC_MITM; + if (settings_get_ble_pairing_enable_first_load()) { + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + } else { + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + } err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); if (err_code != NRF_SUCCESS) @@ -304,12 +308,15 @@ uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) add_char_params.is_var_len = true; add_char_params.char_props.notify = 1; - // add_char_params.read_access = SEC_OPEN; - // add_char_params.write_access = SEC_OPEN; - // add_char_params.cccd_write_access = SEC_OPEN; - add_char_params.read_access = SEC_MITM; - add_char_params.write_access = SEC_MITM; - add_char_params.cccd_write_access = SEC_MITM; + if (settings_get_ble_pairing_enable_first_load()) { + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + add_char_params.cccd_write_access = SEC_MITM; + } else { + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + } return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); /**@snippet [Adding proprietary characteristic to the SoftDevice] */ diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 0a6b190..440e22f 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -162,7 +162,6 @@ hw_ble_bonds = hw_ble.subgroup('bonds', 'All devices bound by chameleons.') hw_settings = hw.subgroup('settings', 'Chameleon settings management') hw_settings_animation = hw_settings.subgroup('animation', 'Manage wake-up and sleep animation modes') hw_settings_button_press = hw_settings.subgroup('btnpress', 'Manage button press function') -hw_settings_ble_key = hw_settings.subgroup('blekey', 'Manage ble connect key') hf = CLITree('hf', 'high frequency tag/reader') hf_14a = hf.subgroup('14a', 'ISO14443-a tag read/write/info...') @@ -1366,35 +1365,64 @@ class HWButtonSettingsSet(DeviceRequiredUnit): print(" - Successfully set button function to settings") -@hw_settings_ble_key.command('set', 'Set the ble connect key') -class HWSettingsBLEKeySet(DeviceRequiredUnit): +@hw_settings.command('blekey', 'Get or set the ble connect key') +class HWSettingsBLEKey(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit or None: parser = ArgumentParserNoExit() - parser.add_argument('-k', '--key', required=True, help="Ble connect key for your device") + parser.add_argument('-k', '--key', required=False, help="Ble connect key for your device") return parser def on_exec(self, args: argparse.Namespace): - if len(args.key) != 6: - print(f" - {colorama.Fore.RED}The ble connect key length must be 6{colorama.Style.RESET_ALL}") - return - if re.match(r'[0-9]{6}', args.key): - self.cmd.set_ble_connect_key(args.key) - print(" - Successfully set ble connect key to settings") - else: - print(f" - {colorama.Fore.RED}Only 6 ASCII characters from 0 to 9 are supported.{colorama.Style.RESET_ALL}") + resp = self.cmd.get_ble_connect_key() + print(" - The current key of the device(ascii): " + f"{colorama.Fore.GREEN}{resp.data.decode(encoding='ascii')}{colorama.Style.RESET_ALL}") + + if args.key != None: + if len(args.key) != 6: + print(f" - {colorama.Fore.RED}The ble connect key length must be 6{colorama.Style.RESET_ALL}") + return + if re.match(r'[0-9]{6}', args.key): + self.cmd.set_ble_connect_key(args.key) + print(" - Successfully set ble connect key to :", end='') + print(f"{colorama.Fore.GREEN}" + f" { args.key }" + f"{colorama.Style.RESET_ALL}" + ) + else: + print(f" - {colorama.Fore.RED}Only 6 ASCII characters from 0 to 9 are supported.{colorama.Style.RESET_ALL}") -@hw_settings_ble_key.command('get', 'Get the ble connect key') -class HWSettingsBLEKeyGet(DeviceRequiredUnit): +@hw_settings.command('blepair', 'Check if BLE pairing is enabled, or set the enable switch for BLE pairing.') +class HWRaw(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit or None: - return None + parser = ArgumentParserNoExit() + parser.add_argument('-e', '--enable', type=int, required=False, help="Enable = 1 or Disable = 0") + return parser def on_exec(self, args: argparse.Namespace): - resp = self.cmd.get_ble_connect_key() - print(" - Key(ascii): " - f"{colorama.Fore.GREEN}{resp.data.decode(encoding='ascii')}{colorama.Style.RESET_ALL}") + is_pairing_enable = self.cmd.get_ble_pairing_enable() + print(f" - Is ble pairing enable: ", end='') + color = colorama.Fore.GREEN if is_pairing_enable else colorama.Fore.RED + print( + f"{color}" + f"{ 'Yes' if is_pairing_enable else 'No' }" + f"{colorama.Style.RESET_ALL}" + ) + if args.enable is not None: + if args.enable == 1 and is_pairing_enable: + print(f"{colorama.Fore.YELLOW} It is already in an enabled state.{colorama.Style.RESET_ALL}") + return + if args.enable == 0 and not is_pairing_enable: + print(f"{colorama.Fore.YELLOW} It is already in a non enabled state.{colorama.Style.RESET_ALL}") + return + self.cmd.set_ble_pairing_enable(args.enable) + print(f" - Successfully change ble pairing to " + f"{colorama.Fore.GREEN if args.enable else colorama.Fore.RED}" + f"{ 'Enable' if args.enable else 'Disable' } " + f"{colorama.Style.RESET_ALL}" + "state.") @hw_ble_bonds.command('clear', 'Clear all bindings') diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index b7a5ca7..e769c90 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -55,6 +55,8 @@ DATA_CMD_DELETE_ALL_BLE_BONDS = 1032 DATA_CMD_GET_DEVICE = 1033 DATA_CMD_GET_SETTINGS = 1034 DATA_CMD_GET_DEVICE_CAPABILITIES = 1035 +DATA_CMD_GET_BLE_PAIRING_ENABLE = 1036 +DATA_CMD_SET_BLE_PAIRING_ENABLE = 1037 DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 @@ -872,6 +874,18 @@ class ChameleonCMD: """ return self.device.send_cmd_sync(DATA_CMD_GET_MF1_ANTI_COLL_DATA, 0x00) + def get_ble_pairing_enable(self) -> bool: + """ + Is ble pairing enable? + :return: True if pairing is enable, False if pairing disabled + """ + resp = self.device.send_cmd_sync(DATA_CMD_GET_BLE_PAIRING_ENABLE, 0x00) + return resp.data[0] == 1 + + @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) + def set_ble_pairing_enable(self, enable: bool): + return self.device.send_cmd_sync(DATA_CMD_SET_BLE_PAIRING_ENABLE, 0x00, 1 if enable else 0) + if __name__ == '__main__': # connect to chameleon