diff --git a/.ci_files/rgb.patch b/.ci_files/rgb.patch index 51a305aec..81783325f 100644 --- a/.ci_files/rgb.patch +++ b/.ci_files/rgb.patch @@ -466,7 +466,7 @@ new file mode 100644 index 0000000..b89f82a --- /dev/null +++ b/lib/drivers/SK6805.c -@@ -0,0 +1,101 @@ +@@ -0,0 +1,103 @@ +/* + SK6805 FlipperZero driver + Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n) @@ -527,6 +527,7 @@ index 0000000..b89f82a +void SK6805_update(void) { + SK6805_init(); + FURI_CRITICAL_ENTER(); ++ furi_delay_us(150); + uint32_t end; + /* Последовательная отправка цветов светодиодов */ + for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) { @@ -566,6 +567,7 @@ index 0000000..b89f82a + } + } + } ++ furi_delay_us(150); + FURI_CRITICAL_EXIT(); +} diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b4d73eb9..81bdd909e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ ## Main changes -- Current API: 79.3 +- Current API: 79.4 * OFW: LFRFID - **EM4305 support** * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes diff --git a/applications/ReadMe.md b/applications/ReadMe.md index a3567df71..02469f252 100644 --- a/applications/ReadMe.md +++ b/applications/ReadMe.md @@ -67,6 +67,7 @@ Small applications providing configuration for basic firmware and its services. - `power_settings_app` - Basic power options - `storage_settings` - Storage settings app - `system` - System settings +- `input_settings_app` - Basic input options ## system diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 843dbebb0..3eda85539 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -149,7 +149,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { if((desktop->settings.usb_inhibit_auto_lock) && (furi_hal_usb_is_locked())) { return (0); } - + desktop_lock(desktop); } } else if(event == DesktopGlobalSaveSettings) { diff --git a/applications/services/input/application.fam b/applications/services/input/application.fam index d344fc350..af6a91339 100644 --- a/applications/services/input/application.fam +++ b/applications/services/input/application.fam @@ -7,4 +7,5 @@ App( stack_size=1 * 1024, order=80, sdk_headers=["input.h"], + provides=["input_settings"], ) diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 6cbafb795..41759a1dd 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -6,12 +6,15 @@ #include #include #include +#include #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) #define INPUT_PRESS_TICKS 150 #define INPUT_LONG_PRESS_COUNTS 2 #define INPUT_THREAD_FLAG_ISR 0x00000001 +#define TAG "Input" + /** Input pin state */ typedef struct { const InputPin* pin; @@ -87,6 +90,11 @@ int32_t input_srv(void* p) { uint32_t counter = 1; furi_record_create(RECORD_INPUT_EVENTS, event_pubsub); + //define object input_settings, take memory load (or init) settings and create record for access to settings structure from outside + InputSettings* settings = malloc(sizeof(InputSettings)); + furi_record_create(RECORD_INPUT_SETTINGS, settings); + input_settings_load(settings); + #ifdef INPUT_DEBUG furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); #endif @@ -149,6 +157,12 @@ int32_t input_srv(void* p) { // Send Press/Release event event.type = pin_states[i].state ? InputTypePress : InputTypeRelease; furi_pubsub_publish(event_pubsub, &event); + // do vibro if user setup vibro touch level in Settings-Input. + if(settings->vibro_touch_level) { + furi_hal_vibro_on(true); + furi_delay_tick(settings->vibro_touch_level); + furi_hal_vibro_on(false); + }; } } diff --git a/applications/services/input/input.h b/applications/services/input/input.h index 5233b4a01..92dbfeb68 100644 --- a/applications/services/input/input.h +++ b/applications/services/input/input.h @@ -6,12 +6,15 @@ #pragma once #include +#include "input_settings.h" +#include #ifdef __cplusplus extern "C" { #endif #define RECORD_INPUT_EVENTS "input_events" +#define RECORD_INPUT_SETTINGS "input_settings" #define INPUT_SEQUENCE_SOURCE_HARDWARE (0u) #define INPUT_SEQUENCE_SOURCE_SOFTWARE (1u) diff --git a/applications/services/input/input_settings.c b/applications/services/input/input_settings.c new file mode 100644 index 000000000..cd3de6d50 --- /dev/null +++ b/applications/services/input/input_settings.c @@ -0,0 +1,59 @@ +#include "input_settings.h" +#include "input_settings_filename.h" + +#include +#include + +#define TAG "InputSettings" + +#define INPUT_SETTINGS_VER (1) // version nnumber + +#define INPUT_SETTINGS_PATH INT_PATH(INPUT_SETTINGS_FILE_NAME) +#define INPUT_SETTINGS_MAGIC (0x29) + +void input_settings_load(InputSettings* settings) { + furi_assert(settings); + + bool success = false; + + //a useless cycle do-while, may will be used in future with anoter condition + do { + // take version from settings file metadata, if cant then break and fill settings with 0 and save to settings file; + uint8_t version; + if(!saved_struct_get_metadata(INPUT_SETTINGS_PATH, NULL, &version, NULL)) break; + + // if config actual version - load it directly + if(version == INPUT_SETTINGS_VER) { + success = saved_struct_load( + INPUT_SETTINGS_PATH, + settings, + sizeof(InputSettings), + INPUT_SETTINGS_MAGIC, + INPUT_SETTINGS_VER); + // if config previous version - load it and inicialize new settings + } + // in case of another config version we exit from useless cycle to next step + } while(false); + + // fill settings with 0 and save to settings file; + if(!success) { + FURI_LOG_W(TAG, "Failed to load file, using defaults"); + memset(settings, 0, sizeof(InputSettings)); + input_settings_save(settings); + } +} + +void input_settings_save(const InputSettings* settings) { + furi_assert(settings); + + const bool success = saved_struct_save( + INPUT_SETTINGS_PATH, + settings, + sizeof(InputSettings), + INPUT_SETTINGS_MAGIC, + INPUT_SETTINGS_VER); + + if(!success) { + FURI_LOG_E(TAG, "Failed to save file"); + } +} diff --git a/applications/services/input/input_settings.h b/applications/services/input/input_settings.h new file mode 100644 index 000000000..376e8e226 --- /dev/null +++ b/applications/services/input/input_settings.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +typedef struct { + uint8_t vibro_touch_level; +} InputSettings; + +#ifdef __cplusplus +extern "C" { +#endif + +void input_settings_load(InputSettings* settings); +void input_settings_save(const InputSettings* settings); + +#ifdef __cplusplus +} +#endif diff --git a/applications/services/input/input_settings_filename.h b/applications/services/input/input_settings_filename.h new file mode 100644 index 000000000..025ed6ad5 --- /dev/null +++ b/applications/services/input/input_settings_filename.h @@ -0,0 +1,3 @@ +#pragma once + +#define INPUT_SETTINGS_FILE_NAME ".input.settings" diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 511c64c78..c6e1147d7 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -442,7 +442,7 @@ static void power_auto_poweroff_timer_callback(void* context) { Power* power = context; //Dont poweroff device if charger connected - if (furi_hal_power_is_charging()) { + if(furi_hal_power_is_charging()) { FURI_LOG_D(TAG, "We dont auto_power_off until battery is charging"); power_start_auto_poweroff_timer(power); } else { @@ -548,6 +548,24 @@ static void power_message_callback(FuriEventLoopObject* object, void* context) { } } +static void power_charge_supress(Power* power) { + // if charge_supress_percent selected (not OFF) and current charge level equal or higher than selected level + // then we start supression if we not supress it before. + if(power->settings.charge_supress_percent && + power->info.charge >= power->settings.charge_supress_percent) { + if(!power->charge_is_supressed) { + power->charge_is_supressed = true; + furi_hal_power_suppress_charge_enter(); + } + // disable supression if charge_supress_percent OFF but charge still supressed + } else { + if(power->charge_is_supressed) { + power->charge_is_supressed = false; + furi_hal_power_suppress_charge_exit(); + } + } +} + static void power_tick_callback(void* context) { furi_assert(context); Power* power = context; @@ -560,6 +578,8 @@ static void power_tick_callback(void* context) { power_check_charging_state(power); // Check and notify about battery level change power_check_battery_level_change(power); + // charge supress arm/disarm + power_charge_supress(power); // Update battery view port if(need_refresh) { view_port_update(power->battery_view_port); @@ -585,7 +605,7 @@ static void power_storage_callback(const void* message, void* context) { } } -// load inital settings from file for power service +// loading and initializing power service settings static void power_init_settings(Power* power) { Storage* storage = furi_record_open(RECORD_STORAGE); furi_pubsub_subscribe(storage_get_pubsub(storage), power_storage_callback, power); @@ -598,6 +618,7 @@ static void power_init_settings(Power* power) { power_settings_load(&power->settings); power_settings_apply(power); furi_record_close(RECORD_STORAGE); + power->charge_is_supressed = false; } static Power* power_alloc(void) { @@ -615,7 +636,7 @@ static Power* power_alloc(void) { free(settings); // auto_poweroff - //---define subscription to loader events message (info about started apps) and defina callback for this + //---define subscription to loader events message (info about started apps) and define callback for this Loader* loader = furi_record_open(RECORD_LOADER); furi_pubsub_subscribe(loader_get_pubsub(loader), power_loader_callback, power); power->input_events_pubsub = furi_record_open(RECORD_INPUT_EVENTS); @@ -661,7 +682,7 @@ int32_t power_srv(void* p) { Power* power = power_alloc(); - // load inital settings for power service + // power service settings initialization power_init_settings(power); power_update_info(power); diff --git a/applications/services/power/power_service/power_i.h b/applications/services/power/power_service/power_i.h index 40b4a1ef4..09f8e7816 100644 --- a/applications/services/power/power_service/power_i.h +++ b/applications/services/power/power_service/power_i.h @@ -41,6 +41,7 @@ struct Power { bool app_running; FuriPubSub* input_events_pubsub; FuriPubSubSubscription* input_events_subscription; + bool charge_is_supressed; }; typedef enum { diff --git a/applications/services/power/power_service/power_settings.c b/applications/services/power/power_service/power_settings.c index 139323a7a..d12754784 100644 --- a/applications/services/power/power_service/power_settings.c +++ b/applications/services/power/power_service/power_settings.c @@ -6,15 +6,15 @@ #define TAG "PowerSettings" -#define POWER_SETTINGS_VER_0 (0) // OLD version number -#define POWER_SETTINGS_VER (1) // NEW actual version nnumber +#define POWER_SETTINGS_VER_1 (1) // Previous version number +#define POWER_SETTINGS_VER (2) // New version number #define POWER_SETTINGS_PATH INT_PATH(POWER_SETTINGS_FILE_NAME) #define POWER_SETTINGS_MAGIC (0x18) typedef struct { - //inital set - empty -} PowerSettingsV0; + uint32_t auto_poweroff_delay_ms; +} PowerSettingsPrevious; void power_settings_load(PowerSettings* settings) { furi_assert(settings); @@ -25,7 +25,8 @@ void power_settings_load(PowerSettings* settings) { uint8_t version; if(!saved_struct_get_metadata(POWER_SETTINGS_PATH, NULL, &version, NULL)) break; - if(version == POWER_SETTINGS_VER) { // if config actual version - load it directly + // if config actual version - load it directly + if(version == POWER_SETTINGS_VER) { success = saved_struct_load( POWER_SETTINGS_PATH, settings, @@ -33,23 +34,22 @@ void power_settings_load(PowerSettings* settings) { POWER_SETTINGS_MAGIC, POWER_SETTINGS_VER); - } else if( - version == - POWER_SETTINGS_VER_0) { // if config previous version - load it and manual set new settings to inital value - PowerSettingsV0* settings_v0 = malloc(sizeof(PowerSettingsV0)); + // if config previous version - load it and manual set new settings to inital value + } else if(version == POWER_SETTINGS_VER_1) { + PowerSettingsPrevious* settings_previous = malloc(sizeof(PowerSettingsPrevious)); success = saved_struct_load( POWER_SETTINGS_PATH, - settings_v0, - sizeof(PowerSettingsV0), + settings_previous, + sizeof(PowerSettingsPrevious), POWER_SETTINGS_MAGIC, - POWER_SETTINGS_VER_0); - + POWER_SETTINGS_VER_1); + // new settings initialization if(success) { - settings->auto_poweroff_delay_ms = 0; + settings->charge_supress_percent = 0; } - free(settings_v0); + free(settings_previous); } } while(false); diff --git a/applications/services/power/power_service/power_settings.h b/applications/services/power/power_service/power_settings.h index 65d8e079e..63f24e097 100644 --- a/applications/services/power/power_service/power_settings.h +++ b/applications/services/power/power_service/power_settings.h @@ -1,16 +1,20 @@ #pragma once #include +#include typedef struct { uint32_t auto_poweroff_delay_ms; + uint8_t charge_supress_percent; } PowerSettings; #ifdef __cplusplus extern "C" { #endif + void power_settings_load(PowerSettings* settings); void power_settings_save(const PowerSettings* settings); + #ifdef __cplusplus } #endif diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 9b992c80c..dfcac3eed 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -52,7 +52,7 @@ const char* const usb_inhibit_auto_lock_delay_text[USB_INHIBIT_AUTO_LOCK_DELAY_C "ON", }; -const uint32_t usb_inhibit_auto_lock_delay_value[USB_INHIBIT_AUTO_LOCK_DELAY_COUNT] = {0,1}; +const uint32_t usb_inhibit_auto_lock_delay_value[USB_INHIBIT_AUTO_LOCK_DELAY_COUNT] = {0, 1}; #define CLOCK_ENABLE_COUNT 2 const char* const clock_enable_text[CLOCK_ENABLE_COUNT] = { diff --git a/applications/settings/input_settings_app/application.fam b/applications/settings/input_settings_app/application.fam new file mode 100644 index 000000000..14be52fc4 --- /dev/null +++ b/applications/settings/input_settings_app/application.fam @@ -0,0 +1,9 @@ +App( + appid="input_settings", + name="Input", + apptype=FlipperAppType.SETTINGS, + entry_point="input_settings_app", + requires=["input"], + stack_size=1 * 1024, + order=100, +) diff --git a/applications/settings/input_settings_app/input_settings_app.c b/applications/settings/input_settings_app/input_settings_app.c new file mode 100644 index 000000000..4f3e101da --- /dev/null +++ b/applications/settings/input_settings_app/input_settings_app.c @@ -0,0 +1,107 @@ +#include +#include "input_settings_app.h" + +#define TAG "InputSettingsApp" + +#define VIBRO_TOUCH_LEVEL_COUNT 10 +// vibro touch human readable levels +const char* const vibro_touch_level_text[VIBRO_TOUCH_LEVEL_COUNT] = { + "OFF", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", +}; +// vibro touch levels tick valies delay +const uint32_t vibro_touch_level_value[VIBRO_TOUCH_LEVEL_COUNT] = + {0, 13, 16, 19, 21, 24, 27, 30, 33, 36}; + +static void input_settings_vibro_touch_level_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, vibro_touch_level_text[index]); + + //change settings to selected + InputSettingsApp* app = variable_item_get_context(item); + app->settings->vibro_touch_level = vibro_touch_level_value[index]; + + // use RECORD for acces to input service instance and set settings + InputSettings* service_settings = furi_record_open(RECORD_INPUT_SETTINGS); + service_settings->vibro_touch_level = vibro_touch_level_value[index]; + furi_record_close(RECORD_INPUT_SETTINGS); +} + +static uint32_t input_settings_app_exit(void* context) { + UNUSED(context); + return VIEW_NONE; +} + +InputSettingsApp* input_settings_app_alloc(void) { + InputSettingsApp* app = malloc(sizeof(InputSettingsApp)); + app->gui = furi_record_open(RECORD_GUI); + + app->settings = malloc(sizeof(InputSettings)); + input_settings_load(app->settings); + + app->variable_item_list = variable_item_list_alloc(); + View* view = variable_item_list_get_view(app->variable_item_list); + view_set_previous_callback(view, input_settings_app_exit); + + VariableItem* item; + uint8_t value_index; + + item = variable_item_list_add( + app->variable_item_list, + "Buttons Vibro", + VIBRO_TOUCH_LEVEL_COUNT, + input_settings_vibro_touch_level_changed, + app); + + value_index = value_index_uint32( + app->settings->vibro_touch_level, vibro_touch_level_value, VIBRO_TOUCH_LEVEL_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, vibro_touch_level_text[value_index]); + + // create and setup view and view dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + view_dispatcher_add_view(app->view_dispatcher, InputSettingsViewVariableItemList, view); + view_dispatcher_switch_to_view(app->view_dispatcher, InputSettingsViewVariableItemList); + + return app; +} + +void input_settings_app_free(InputSettingsApp* app) { + furi_assert(app); + + // Variable item list + view_dispatcher_remove_view(app->view_dispatcher, InputSettingsViewVariableItemList); + variable_item_list_free(app->variable_item_list); + + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + + // Records + furi_record_close(RECORD_GUI); + free(app->settings); + free(app); +} + +// Enter point +int32_t input_settings_app(void* p) { + UNUSED(p); + InputSettingsApp* app = input_settings_app_alloc(); + + view_dispatcher_run(app->view_dispatcher); + + //save current settings; + input_settings_save(app->settings); + + input_settings_app_free(app); + return 0; +} diff --git a/applications/settings/input_settings_app/input_settings_app.h b/applications/settings/input_settings_app/input_settings_app.h new file mode 100644 index 000000000..c96ca49e9 --- /dev/null +++ b/applications/settings/input_settings_app/input_settings_app.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// input_settings_app stucture +typedef struct { + Gui* gui; + ViewDispatcher* view_dispatcher; + VariableItemList* variable_item_list; + InputSettings* settings; +} InputSettingsApp; + +// list of menu views for view dispatcher +typedef enum { + InputSettingsViewVariableItemList, +} InputSettingsView; diff --git a/applications/settings/power_settings_app/scenes/power_settings_scene_start.c b/applications/settings/power_settings_app/scenes/power_settings_scene_start.c index 3fc3a8a30..42c53ed02 100644 --- a/applications/settings/power_settings_app/scenes/power_settings_scene_start.c +++ b/applications/settings/power_settings_app/scenes/power_settings_scene_start.c @@ -15,6 +15,21 @@ const char* const auto_poweroff_delay_text[AUTO_POWEROFF_DELAY_COUNT] = const uint32_t auto_poweroff_delay_value[AUTO_POWEROFF_DELAY_COUNT] = {0, 300000, 600000, 900000, 1800000, 2700000, 3600000, 5400000}; +#define CHARGE_SUPRESS_PERCENT_COUNT 6 +const char* const charge_supress_percent_text[CHARGE_SUPRESS_PERCENT_COUNT] = + {"OFF", "90%", "85%", "80%", "75%", "70%"}; + +const uint32_t charge_supress_percent_value[CHARGE_SUPRESS_PERCENT_COUNT] = {0, 90, 85, 80, 75, 70}; + +// change variable_item_list visible text and charge_supress_percent_settings when user change item in variable_item_list +static void power_settings_scene_start_charge_supress_percent_changed(VariableItem* item) { + PowerSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, charge_supress_percent_text[index]); + app->settings.charge_supress_percent = charge_supress_percent_value[index]; +} + // change variable_item_list visible text and app_poweroff_delay_time_settings when user change item in variable_item_list static void power_settings_scene_start_auto_poweroff_delay_changed(VariableItem* item) { PowerSettingsApp* app = variable_item_get_context(item); @@ -24,9 +39,8 @@ static void power_settings_scene_start_auto_poweroff_delay_changed(VariableItem* app->settings.auto_poweroff_delay_ms = auto_poweroff_delay_value[index]; } -static void power_settings_scene_start_submenu_callback( - void* context, - uint32_t index) { //show selected menu screen +static void power_settings_scene_start_submenu_callback(void* context, uint32_t index) { + //show selected menu screen by index furi_assert(context); PowerSettingsApp* app = context; view_dispatcher_send_custom_event(app->view_dispatcher, index); @@ -42,11 +56,12 @@ void power_settings_scene_start_on_enter(void* context) { VariableItem* item; uint8_t value_index; + item = variable_item_list_add( variable_item_list, "Auto PowerOff", AUTO_POWEROFF_DELAY_COUNT, - power_settings_scene_start_auto_poweroff_delay_changed, //function for change visible item list value and app settings + power_settings_scene_start_auto_poweroff_delay_changed, app); value_index = value_index_uint32( @@ -56,14 +71,25 @@ void power_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, auto_poweroff_delay_text[value_index]); + item = variable_item_list_add( + variable_item_list, + "Limit Charge", + CHARGE_SUPRESS_PERCENT_COUNT, + power_settings_scene_start_charge_supress_percent_changed, + app); + + value_index = value_index_uint32( + app->settings.charge_supress_percent, + charge_supress_percent_value, + CHARGE_SUPRESS_PERCENT_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, charge_supress_percent_text[value_index]); + variable_item_list_set_selected_item( variable_item_list, scene_manager_get_scene_state(app->scene_manager, PowerSettingsAppSceneStart)); - variable_item_list_set_enter_callback( //callback to show next mennu screen - variable_item_list, - power_settings_scene_start_submenu_callback, - app); - + variable_item_list_set_enter_callback( + variable_item_list, power_settings_scene_start_submenu_callback, app); view_dispatcher_switch_to_view(app->view_dispatcher, PowerSettingsAppViewVariableItemList); } @@ -88,5 +114,5 @@ bool power_settings_scene_start_on_event(void* context, SceneManagerEvent event) void power_settings_scene_start_on_exit(void* context) { PowerSettingsApp* app = context; variable_item_list_reset(app->variable_item_list); - power_settings_save(&app->settings); //actual need save every time when use ? + power_settings_save(&app->settings); } diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 79a195924..bfb84a0c8 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,79.3,, +Version,+,79.4,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, @@ -2114,6 +2114,8 @@ Function,+,infrared_worker_tx_stop,void,InfraredWorker* Function,-,initstate,char*,"unsigned, char*, size_t" Function,+,input_get_key_name,const char*,InputKey Function,+,input_get_type_name,const char*,InputType +Function,+,input_settings_load,void,InputSettings* +Function,+,input_settings_save,void,const InputSettings* Function,-,iprintf,int,"const char*, ..." Function,-,isalnum,int,int Function,-,isalnum_l,int,"int, locale_t"