New way of changing device name

Settings scene, char Validator, Idea -> by Willy-JL
Implemented by me

Kod plohoi, ochen plohoi, kto mozhet - sdelaite kak nado, esli smozhete :)
Ya luche varianta ne pridumal poka 4to
This commit is contained in:
MX 2023-05-14 05:38:00 +03:00
parent bdc720ac7d
commit c2713eff87
No known key found for this signature in database
GPG key ID: 7CCC66B7DBDD1C83
20 changed files with 316 additions and 72 deletions

View file

@ -9,6 +9,9 @@
#include <cli/cli.h>
#include <cli/cli_vcp.h>
#include <toolbox/namechanger.h>
#include <bt/bt_service/bt.h>
#include "animations/animation_manager.h"
#include "desktop/scenes/desktop_scene.h"
#include "desktop/scenes/desktop_scene_i.h"
@ -426,6 +429,26 @@ int32_t desktop_srv(void* p) {
scene_manager_next_scene(desktop->scene_manager, DesktopSceneFault);
}
// I added some very bydlo kod here, and thrown some delays to make it worse, pls don't look at it, it will make you cry from laugh
if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) {
if(NameChanger_Init()) {
Cli* cli = furi_record_open(RECORD_CLI);
cli_session_close(cli);
furi_delay_ms(2);
cli_session_open(cli, &cli_vcp);
furi_record_close(RECORD_CLI);
furi_delay_ms(3);
Bt* bt = furi_record_open(RECORD_BT);
if(!bt_set_profile(bt, BtProfileSerial)) {
FURI_LOG_D(TAG, "Failed to touch bluetooth to name change");
}
furi_record_close(RECORD_BT);
bt = NULL;
furi_delay_ms(3);
}
}
view_dispatcher_run(desktop->view_dispatcher);
desktop_free(desktop);

View file

@ -41,7 +41,7 @@ void popup_free(Popup* popup);
*/
View* popup_get_view(Popup* popup);
/** Set popup header text
/** Set popup callback function
*
* @param popup Popup instance
* @param callback PopupCallback

View file

@ -1,6 +1,9 @@
#include <furi.h>
#include <gui/modules/popup.h>
#include <gui/scene_manager.h>
#include <toolbox/namechanger.h>
#include <flipper_format/flipper_format.h>
#include <power/power_service/power.h>
#include "desktop_settings_app.h"
#include "scenes/desktop_settings_scene.h"
@ -62,11 +65,41 @@ DesktopSettingsApp* desktop_settings_app_alloc() {
app->view_dispatcher,
DesktopSettingsAppViewIdPinSetupHowto2,
desktop_settings_view_pin_setup_howto2_get_view(app->pin_setup_howto2_view));
// Text Input
app->text_input = text_input_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
DesktopSettingsAppViewTextInput,
text_input_get_view(app->text_input));
return app;
}
void desktop_settings_app_free(DesktopSettingsApp* app) {
furi_assert(app);
bool temp_save_name = app->save_name;
// Save name if set or remove file
if(temp_save_name) {
Storage* storage = furi_record_open(RECORD_STORAGE);
if(strcmp(app->device_name, "") == 0) {
storage_simply_remove(storage, NAMECHANGER_PATH);
} else {
FlipperFormat* file = flipper_format_file_alloc(storage);
do {
if(!flipper_format_file_open_always(file, NAMECHANGER_PATH)) break;
if(!flipper_format_write_header_cstr(file, NAMECHANGER_HEADER, NAMECHANGER_VERSION))
break;
if(!flipper_format_write_string_cstr(file, "Name", app->device_name)) break;
} while(0);
flipper_format_free(file);
}
furi_record_close(RECORD_STORAGE);
}
// Variable item list
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
@ -74,6 +107,10 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinInput);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto);
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewIdPinSetupHowto2);
// TextInput
view_dispatcher_remove_view(app->view_dispatcher, DesktopSettingsAppViewTextInput);
text_input_free(app->text_input);
variable_item_list_free(app->variable_item_list);
submenu_free(app->submenu);
popup_free(app->popup);
@ -87,6 +124,10 @@ void desktop_settings_app_free(DesktopSettingsApp* app) {
furi_record_close(RECORD_DIALOGS);
furi_record_close(RECORD_GUI);
free(app);
if(temp_save_name) {
power_reboot(PowerBootModeNormal);
}
}
extern int32_t desktop_settings_app(void* p) {

View file

@ -6,6 +6,7 @@
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/text_input.h>
#include <dialogs/dialogs.h>
#include <assets_icons.h>
@ -21,6 +22,7 @@ typedef enum {
DesktopSettingsAppViewIdPinInput,
DesktopSettingsAppViewIdPinSetupHowto,
DesktopSettingsAppViewIdPinSetupHowto2,
DesktopSettingsAppViewTextInput,
} DesktopSettingsAppView;
typedef struct {
@ -32,6 +34,7 @@ typedef struct {
ViewDispatcher* view_dispatcher;
VariableItemList* variable_item_list;
Submenu* submenu;
TextInput* text_input;
Popup* popup;
DesktopViewPinInput* pin_input_view;
DesktopSettingsViewPinSetupHowto* pin_setup_howto_view;
@ -40,5 +43,8 @@ typedef struct {
PinCode pincode_buffer;
bool pincode_buffer_filled;
bool save_name;
char device_name[FURI_HAL_VERSION_ARRAY_NAME_LENGTH];
uint8_t menu_idx;
} DesktopSettingsApp;

View file

@ -0,0 +1,75 @@
#include "../desktop_settings_app.h"
#include <desktop/desktop_settings.h>
#include "desktop_settings_scene.h"
enum TextInputIndex {
TextInputResultOk,
};
static void desktop_settings_scene_change_name_text_input_callback(void* context) {
DesktopSettingsApp* app = context;
app->save_name = true;
view_dispatcher_send_custom_event(app->view_dispatcher, TextInputResultOk);
}
static bool desktop_settings_scene_change_name_validator(
const char* text,
FuriString* error,
void* context) {
UNUSED(context);
for(; *text; ++text) {
const char c = *text;
if((c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
furi_string_printf(error, "Please only\nenter letters\nand numbers!");
return false;
}
}
return true;
}
void desktop_settings_scene_change_name_on_enter(void* context) {
DesktopSettingsApp* app = context;
TextInput* text_input = app->text_input;
text_input_set_header_text(text_input, "Leave empty for default");
text_input_set_validator(text_input, desktop_settings_scene_change_name_validator, NULL);
text_input_set_minimum_length(text_input, 0);
text_input_set_result_callback(
text_input,
desktop_settings_scene_change_name_text_input_callback,
app,
app->device_name,
FURI_HAL_VERSION_ARRAY_NAME_LENGTH,
true);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewTextInput);
}
bool desktop_settings_scene_change_name_on_event(void* context, SceneManagerEvent event) {
DesktopSettingsApp* app = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
consumed = true;
switch(event.event) {
case TextInputResultOk:
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneNamePopup);
break;
default:
break;
}
}
return consumed;
}
void desktop_settings_scene_change_name_on_exit(void* context) {
DesktopSettingsApp* app = context;
text_input_reset(app->text_input);
}

View file

@ -9,3 +9,6 @@ ADD_SCENE(desktop_settings, pin_setup, PinSetup)
ADD_SCENE(desktop_settings, pin_setup_howto, PinSetupHowto)
ADD_SCENE(desktop_settings, pin_setup_howto2, PinSetupHowto2)
ADD_SCENE(desktop_settings, pin_setup_done, PinSetupDone)
ADD_SCENE(desktop_settings, change_name, ChangeName)
ADD_SCENE(desktop_settings, name_popup, NamePopup)

View file

@ -0,0 +1,54 @@
#include <stdint.h>
#include <core/check.h>
#include <gui/scene_manager.h>
#include <gui/modules/popup.h>
#include "../desktop_settings_app.h"
#include <desktop/desktop_settings.h>
#include "desktop_settings_scene.h"
#define SCENE_EVENT_EXIT (0U)
static void name_popup_back_callback(void* context) {
furi_assert(context);
DesktopSettingsApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, SCENE_EVENT_EXIT);
}
void desktop_settings_scene_name_popup_on_enter(void* context) {
furi_assert(context);
DesktopSettingsApp* app = context;
popup_set_context(app->popup, app);
popup_set_callback(app->popup, name_popup_back_callback);
popup_set_header(app->popup, "Name is set!", 64, 20, AlignCenter, AlignCenter);
popup_set_text(
app->popup, "Your Flipper will be\nrestarted on exit.", 64, 40, AlignCenter, AlignCenter);
popup_set_timeout(app->popup, 2100);
popup_enable_timeout(app->popup);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup);
}
bool desktop_settings_scene_name_popup_on_event(void* context, SceneManagerEvent event) {
DesktopSettingsApp* app = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
switch(event.event) {
case SCENE_EVENT_EXIT:
scene_manager_search_and_switch_to_previous_scene(
app->scene_manager, DesktopSettingsAppSceneStart);
consumed = true;
break;
default:
consumed = true;
break;
}
}
return consumed;
}
void desktop_settings_scene_name_popup_on_exit(void* context) {
UNUSED(context);
}

View file

@ -11,6 +11,7 @@
#define SCENE_EVENT_SELECT_PIN_SETUP 3
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 4
#define SCENE_EVENT_SELECT_BATTERY_DISPLAY 5
#define SCENE_EVENT_SELECT_CHANGE_NAME 6
#define AUTO_LOCK_DELAY_COUNT 9
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
@ -105,6 +106,8 @@ void desktop_settings_scene_start_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, battery_view_count_text[value_index]);
variable_item_list_add(variable_item_list, "Change Flipper Name", 0, NULL, app);
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
}
@ -139,6 +142,10 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
case SCENE_EVENT_SELECT_BATTERY_DISPLAY:
consumed = true;
break;
case SCENE_EVENT_SELECT_CHANGE_NAME:
scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneChangeName);
consumed = true;
break;
}
}
return consumed;

View file

@ -1,35 +1,10 @@
# How to change Flipper name:
## Instruction
1. Read [How to build](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md) and [How to install](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md) to know how to build and install firmware
2. Follow how to build instructions to prepare all things before continuing
3. Run release build to verify all is ok - `./fbt COMPACT=1 DEBUG=0 updater_package`
4. Clear build files - `./fbt COMPACT=1 DEBUG=0 updater_package -c`
5. Run command with extra environment var before `./fbt` that variable should contain your custom name in alphanumeric characters - max length 8 chars
`CUSTOM_FLIPPER_NAME=Name ./fbt COMPACT=1 DEBUG=0 updater_package` - where `Name` write your custom name
6. Copy `dist/f7-C/f7-update-local` folder to microSD `update/myfw/` and run `update` file on flipper from file manager app (Archive)
7. Flash from microSD card only!!!! .dfu update from qFlipper will not work properly since name and serial number will be changed
8. Done, you will have custom name, serial number and bluetooth mac address
1. Go to Settings -> Desktop -> Change Flipper Name
2. Enter your new custom name for your flipper and click `Save`, **name will be saved on microSD card, and will stay same after firmware updates**
3. You will see a message `Name is set!` and when you exit from settings -> flipper will automatically reboot!
4. After reboot you will see your new custom name in device info and right screen `passport`
5. Done!
9. Also you can skip 5-7 and flash with `CUSTOM_FLIPPER_NAME=Name ./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full`
## Troubleshooting
### I'm using Windows and name changing / building firmware doesn't work
- Use PowerShell or VSCode terminal(powershell by default)
- Clear build files - `.\fbt.cmd COMPACT=1 DEBUG=0 updater_package -c`
- Enter this in same terminal `$Env:CUSTOM_FLIPPER_NAME="Name"`
- Run release build - `.\fbt.cmd COMPACT=1 DEBUG=0 updater_package`
- Flash as described before (see 6.)
- If something still not work - Run powershell or VSCode as Admin
### Name stays same for every new build
- Clear build files - `./fbt COMPACT=1 DEBUG=0 updater_package -c`
- Try again
### I want to return my original name and serial number
- Flash stock FW or any CFW using microSD card offline update method
Or
- Clear build files - `./fbt COMPACT=1 DEBUG=0 updater_package -c`
- Run release build - `./fbt COMPACT=1 DEBUG=0 updater_package`
- Copy `dist/f7-C/f7-update-local` folder to microSD `update/myfw/` and run `update` file on flipper from file manager app (Archive)
- Flash from microSD card only, .dfu update from qFlipper will not work properly since name and serial number will be changed
**To reset device name to default - do same steps but do not enter any characters, leave it empty and click** `Save`

View file

@ -1486,6 +1486,7 @@ Function,+,furi_hal_version_get_model_name,const char*,
Function,+,furi_hal_version_get_name_ptr,const char*,
Function,+,furi_hal_version_get_otp_version,FuriHalVersionOtpVersion,
Function,-,furi_hal_version_init,void,
Function,-,furi_hal_version_set_name,void,const char*
Function,+,furi_hal_version_uid,const uint8_t*,
Function,+,furi_hal_version_uid_size,size_t,
Function,-,furi_hal_vibro_init,void,
@ -4597,6 +4598,7 @@ Function,+,version_get_gitbranchnum,const char*,const Version*
Function,+,version_get_githash,const char*,const Version*
Function,+,version_get_target,uint8_t,const Version*
Function,+,version_get_version,const char*,const Version*
Function,-,version_set_custom_name,void,"Version*, const char*"
Function,-,vfiprintf,int,"FILE*, const char*, __gnuc_va_list"
Function,-,vfiscanf,int,"FILE*, const char*, __gnuc_va_list"
Function,-,vfprintf,int,"FILE*, const char*, __gnuc_va_list"

1 entry status name type params
1486 Function + furi_hal_version_get_name_ptr const char*
1487 Function + furi_hal_version_get_otp_version FuriHalVersionOtpVersion
1488 Function - furi_hal_version_init void
1489 Function - furi_hal_version_set_name void const char*
1490 Function + furi_hal_version_uid const uint8_t*
1491 Function + furi_hal_version_uid_size size_t
1492 Function - furi_hal_vibro_init void
4598 Function + version_get_githash const char* const Version*
4599 Function + version_get_target uint8_t const Version*
4600 Function + version_get_version const char* const Version*
4601 Function - version_set_custom_name void Version*, const char*
4602 Function - vfiprintf int FILE*, const char*, __gnuc_va_list
4603 Function - vfiscanf int FILE*, const char*, __gnuc_va_list
4604 Function - vfprintf int FILE*, const char*, __gnuc_va_list

View file

@ -90,7 +90,7 @@ typedef struct {
static FuriHalVersion furi_hal_version = {0};
static void furi_hal_version_set_name(const char* name) {
void furi_hal_version_set_name(const char* name) {
if(name != NULL) {
strlcpy(furi_hal_version.name, name, FURI_HAL_VERSION_ARRAY_NAME_LENGTH);
snprintf(

View file

@ -176,6 +176,10 @@ const char* furi_hal_version_get_device_name_ptr();
*/
const char* furi_hal_version_get_ble_local_device_name_ptr();
/** Set flipper name
*/
void furi_hal_version_set_name(const char* name);
/** Get BLE MAC address
*
* @return pointer to BLE MAC address

53
lib/toolbox/namechanger.c Normal file
View file

@ -0,0 +1,53 @@
#include "namechanger.h"
#include <furi_hal_version.h>
#include <flipper_format/flipper_format.h>
#define TAG "NameChanger"
bool NameChanger_Init() {
Storage* storage = furi_record_open(RECORD_STORAGE);
FuriString* str = furi_string_alloc();
FlipperFormat* file = flipper_format_file_alloc(storage);
bool res = false;
do {
uint32_t version;
if(!flipper_format_file_open_existing(file, NAMECHANGER_PATH)) break;
if(!flipper_format_read_header(file, str, &version)) break;
if(furi_string_cmp_str(str, NAMECHANGER_HEADER)) break;
if(version != NAMECHANGER_VERSION) break;
if(!flipper_format_read_string(file, "Name", str)) break;
// Check for size
size_t temp_string_size = furi_string_size(str);
if(temp_string_size > (size_t)8) break;
if(temp_string_size < (size_t)2) break;
// Check for forbidden characters
const char* name_ptr = furi_string_get_cstr(str);
bool chars_check_failed = false;
for(; *name_ptr; ++name_ptr) {
const char c = *name_ptr;
if((c < '0' || c > '9') && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
chars_check_failed = true;
break;
}
}
if(chars_check_failed) break;
// If all checks was good we can set the name
version_set_custom_name(NULL, strdup(furi_string_get_cstr(str)));
furi_hal_version_set_name(version_get_custom_name(NULL));
res = true;
} while(false);
flipper_format_free(file);
furi_record_close(RECORD_STORAGE);
furi_string_free(str);
return res;
}

18
lib/toolbox/namechanger.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#define NAMECHANGER_HEADER "Flipper Name File"
#define NAMECHANGER_VERSION 1
#define NAMECHANGER_PATH EXT_PATH("dolphin/name.settings")
#include "stdbool.h"
#ifdef __cplusplus
extern "C" {
#endif
// Initializes the name changer. (Load name file, apply changes)
bool NameChanger_Init();
#ifdef __cplusplus
}
#endif

View file

@ -24,18 +24,14 @@ struct Version {
};
/* version of current running firmware (bootloader/flipper) */
static const Version version = {
static Version version = {
.magic = VERSION_MAGIC,
.major = VERSION_MAJOR,
.minor = VERSION_MINOR,
.git_hash = GIT_COMMIT,
.git_branch = GIT_BRANCH,
.build_date = BUILD_DATE,
#ifdef FURI_CUSTOM_FLIPPER_NAME
.custom_flipper_name = FURI_CUSTOM_FLIPPER_NAME,
#else
.custom_flipper_name = NULL,
#endif
.version = VERSION
#ifdef FURI_RAM_EXEC
" (RAM)"
@ -74,6 +70,12 @@ const char* version_get_custom_name(const Version* v) {
return v ? v->custom_flipper_name : version.custom_flipper_name;
}
void version_set_custom_name(Version* v, const char* name) {
Version* ver = v ? v : &version;
ver->custom_flipper_name = name;
return;
}
uint8_t version_get_target(const Version* v) {
return v ? v->target : version.target;
}

View file

@ -65,7 +65,7 @@ const char* version_get_builddate(const Version* v);
*/
const char* version_get_version(const Version* v);
/** Get custom flipper name if set in ENV
/** Get custom flipper name if set in version_set_custom_name
*
* @param v pointer to Version data. NULL for currently running
* software.
@ -74,6 +74,14 @@ const char* version_get_version(const Version* v);
*/
const char* version_get_custom_name(const Version* v);
/** Set custom flipper name
*
* @param v pointer to Version data. NULL for currently running
* software.
* @param name Custom name or NULL
*/
void version_set_custom_name(Version* v, const char* name);
/** Get hardware target this firmware was built for
*
* @param v pointer to Version data. NULL for currently running

View file

@ -250,13 +250,6 @@ class Main(App):
)
bundle_args.extend(self.other_args)
log_custom_fz_name = (
environ.get("CUSTOM_FLIPPER_NAME", None)
or ""
)
if (log_custom_fz_name != "") and (len(log_custom_fz_name) <= 8) and (log_custom_fz_name.isalnum()) and (log_custom_fz_name.isascii()):
self.logger.info(f"Flipper Custom Name is set:\n\tName: {log_custom_fz_name} : length - {len(log_custom_fz_name)} chars")
if (bundle_result := UpdateMain(no_exit=True)(bundle_args)) == 0:
self.note_dist_component("update", "dir", bundle_dir)
self.logger.info(

View file

@ -40,11 +40,6 @@ class GitVersion:
or "unknown"
)
custom_fz_name = (
os.environ.get("CUSTOM_FLIPPER_NAME", None)
or ""
)
force_no_dirty = (
os.environ.get("FORCE_NO_DIRTY", None)
or ""
@ -52,21 +47,12 @@ class GitVersion:
if (force_no_dirty != ""):
dirty = False
if (custom_fz_name != "") and (len(custom_fz_name) <= 8) and (custom_fz_name.isalnum()) and (custom_fz_name.isascii()):
return {
"GIT_COMMIT": commit,
"GIT_BRANCH": branch,
"FURI_CUSTOM_FLIPPER_NAME": custom_fz_name,
"VERSION": version,
"BUILD_DIRTY": dirty and 1 or 0,
}
else:
return {
"GIT_COMMIT": commit,
"GIT_BRANCH": branch,
"VERSION": version,
"BUILD_DIRTY": dirty and 1 or 0,
}
return {
"GIT_COMMIT": commit,
"GIT_BRANCH": branch,
"VERSION": version,
"BUILD_DIRTY": dirty and 1 or 0,
}
def _exec_git(self, args):
cmd = ["git"]

View file

@ -100,11 +100,6 @@ vars.AddVariables(
"Version string for updater package",
"${DIST_SUFFIX}",
),
(
"CUSTOM_FLIPPER_NAME",
"Replaces OTP flipper name with custom string of 8 chars",
"",
),
(
"FORCE_NO_DIRTY",
"Force disable dirty status of the build",

View file

@ -20,7 +20,6 @@ variables_to_forward = [
# CI/CD variables
"WORKFLOW_BRANCH_OR_TAG",
"DIST_SUFFIX",
"CUSTOM_FLIPPER_NAME",
"FORCE_NO_DIRTY",
# Python & other tools
"HOME",