Merge branch 'ofw-dev' into dev
@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32);
|
||||
dialog_ex_set_icon(dialog_ex, 5, 11, &I_ArrowC_1_36x36);
|
||||
dialog_ex_set_text(
|
||||
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
||||
|
@ -75,6 +75,8 @@ typedef enum {
|
||||
NotificationMessageTypeForceDisplayBrightnessSetting,
|
||||
|
||||
NotificationMessageTypeLedBrightnessSettingApply,
|
||||
|
||||
NotificationMessageTypeLcdContrastUpdate,
|
||||
} NotificationMessageType;
|
||||
|
||||
typedef struct {
|
||||
|
@ -3,6 +3,9 @@
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <input/input.h>
|
||||
#include <gui/gui_i.h>
|
||||
#include <u8g2_glue.h>
|
||||
|
||||
#include "notification.h"
|
||||
#include "notification_messages.h"
|
||||
#include "notification_app.h"
|
||||
@ -20,14 +23,14 @@ static const uint8_t reset_sound_mask = 1 << 4;
|
||||
static const uint8_t reset_display_mask = 1 << 5;
|
||||
static const uint8_t reset_blink_mask = 1 << 6;
|
||||
|
||||
void notification_vibro_on(bool force);
|
||||
void notification_vibro_off();
|
||||
void notification_sound_on(float freq, float volume, bool force);
|
||||
void notification_sound_off();
|
||||
static void notification_vibro_on(bool force);
|
||||
static void notification_vibro_off();
|
||||
static void notification_sound_on(float freq, float volume, bool force);
|
||||
static void notification_sound_off();
|
||||
|
||||
uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value);
|
||||
uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value);
|
||||
uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app);
|
||||
static uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value);
|
||||
static uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value);
|
||||
static uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app);
|
||||
|
||||
void notification_message_save_settings(NotificationApp* app) {
|
||||
NotificationAppMessage m = {
|
||||
@ -39,7 +42,8 @@ void notification_message_save_settings(NotificationApp* app) {
|
||||
};
|
||||
|
||||
// internal layer
|
||||
void notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t layer_value) {
|
||||
static void
|
||||
notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t layer_value) {
|
||||
furi_assert(layer);
|
||||
furi_assert(layer->index < LayerMAX);
|
||||
|
||||
@ -52,7 +56,13 @@ void notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t
|
||||
}
|
||||
}
|
||||
|
||||
bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app) {
|
||||
static void notification_apply_lcd_contrast(NotificationApp* app) {
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
u8x8_d_st756x_set_contrast(&gui->canvas->fb.u8x8, app->settings.contrast);
|
||||
furi_record_close(RECORD_GUI);
|
||||
}
|
||||
|
||||
static bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app) {
|
||||
bool result = false;
|
||||
if((app->led[0].index == LayerInternal) || (app->led[1].index == LayerInternal) ||
|
||||
(app->led[2].index == LayerInternal)) {
|
||||
@ -67,7 +77,7 @@ bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app)
|
||||
}
|
||||
|
||||
// notification layer
|
||||
void notification_apply_notification_led_layer(
|
||||
static void notification_apply_notification_led_layer(
|
||||
NotificationLedLayer* layer,
|
||||
const uint8_t layer_value) {
|
||||
furi_assert(layer);
|
||||
@ -81,7 +91,7 @@ void notification_apply_notification_led_layer(
|
||||
furi_hal_light_set(layer->light, layer->value[LayerNotification]);
|
||||
}
|
||||
|
||||
void notification_reset_notification_led_layer(NotificationLedLayer* layer) {
|
||||
static void notification_reset_notification_led_layer(NotificationLedLayer* layer) {
|
||||
furi_assert(layer);
|
||||
furi_assert(layer->index < LayerMAX);
|
||||
|
||||
@ -94,7 +104,7 @@ void notification_reset_notification_led_layer(NotificationLedLayer* layer) {
|
||||
furi_hal_light_set(layer->light, layer->value[LayerInternal]);
|
||||
}
|
||||
|
||||
void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) {
|
||||
static void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) {
|
||||
if(reset_mask & reset_blink_mask) {
|
||||
furi_hal_light_blink_stop();
|
||||
}
|
||||
@ -130,28 +140,28 @@ uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8
|
||||
return (value * app->settings.display_brightness);
|
||||
}
|
||||
|
||||
uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value) {
|
||||
static uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value) {
|
||||
return (value * app->settings.led_brightness);
|
||||
}
|
||||
|
||||
uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app) {
|
||||
static uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app) {
|
||||
return (
|
||||
(float)(app->settings.display_off_delay_ms) /
|
||||
(1000.0f / furi_kernel_get_tick_frequency()));
|
||||
}
|
||||
|
||||
// generics
|
||||
void notification_vibro_on(bool force) {
|
||||
static void notification_vibro_on(bool force) {
|
||||
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) {
|
||||
furi_hal_vibro_on(true);
|
||||
}
|
||||
}
|
||||
|
||||
void notification_vibro_off() {
|
||||
static void notification_vibro_off() {
|
||||
furi_hal_vibro_on(false);
|
||||
}
|
||||
|
||||
void notification_sound_on(float freq, float volume, bool force) {
|
||||
static void notification_sound_on(float freq, float volume, bool force) {
|
||||
if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) {
|
||||
if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
|
||||
furi_hal_speaker_start(freq, volume);
|
||||
@ -159,7 +169,7 @@ void notification_sound_on(float freq, float volume, bool force) {
|
||||
}
|
||||
}
|
||||
|
||||
void notification_sound_off() {
|
||||
static void notification_sound_off() {
|
||||
if(furi_hal_speaker_is_mine()) {
|
||||
furi_hal_speaker_stop();
|
||||
furi_hal_speaker_release();
|
||||
@ -174,7 +184,7 @@ static void notification_display_timer(void* ctx) {
|
||||
}
|
||||
|
||||
// message processing
|
||||
void notification_process_notification_message(
|
||||
static void notification_process_notification_message(
|
||||
NotificationApp* app,
|
||||
NotificationAppMessage* message) {
|
||||
uint32_t notification_message_index = 0;
|
||||
@ -333,6 +343,9 @@ void notification_process_notification_message(
|
||||
reset_mask |= reset_green_mask;
|
||||
reset_mask |= reset_blue_mask;
|
||||
break;
|
||||
case NotificationMessageTypeLcdContrastUpdate:
|
||||
notification_apply_lcd_contrast(app);
|
||||
break;
|
||||
}
|
||||
notification_message_index++;
|
||||
notification_message = (*message->sequence)[notification_message_index];
|
||||
@ -361,7 +374,8 @@ void notification_process_notification_message(
|
||||
}
|
||||
}
|
||||
|
||||
void notification_process_internal_message(NotificationApp* app, NotificationAppMessage* message) {
|
||||
static void
|
||||
notification_process_internal_message(NotificationApp* app, NotificationAppMessage* message) {
|
||||
uint32_t notification_message_index = 0;
|
||||
const NotificationMessage* notification_message;
|
||||
notification_message = (*message->sequence)[notification_message_index];
|
||||
@ -548,6 +562,7 @@ int32_t notification_srv(void* p) {
|
||||
notification_apply_internal_led_layer(&app->led[0], 0x00);
|
||||
notification_apply_internal_led_layer(&app->led[1], 0x00);
|
||||
notification_apply_internal_led_layer(&app->led[2], 0x00);
|
||||
notification_apply_lcd_contrast(app);
|
||||
|
||||
furi_record_create(RECORD_NOTIFICATION, app);
|
||||
|
||||
|
@ -32,7 +32,7 @@ typedef struct {
|
||||
Light light;
|
||||
} NotificationLedLayer;
|
||||
|
||||
#define NOTIFICATION_SETTINGS_VERSION 0x01
|
||||
#define NOTIFICATION_SETTINGS_VERSION 0x02
|
||||
#define NOTIFICATION_SETTINGS_PATH INT_PATH(NOTIFICATION_SETTINGS_FILE_NAME)
|
||||
|
||||
typedef struct {
|
||||
@ -41,6 +41,7 @@ typedef struct {
|
||||
float led_brightness;
|
||||
float speaker_volume;
|
||||
uint32_t display_off_delay_ms;
|
||||
int8_t contrast;
|
||||
bool vibro_on;
|
||||
} NotificationSettings;
|
||||
|
||||
|
@ -197,6 +197,10 @@ const NotificationMessage message_force_display_brightness_setting_1f = {
|
||||
.data.forced_settings.display_brightness = 1.0f,
|
||||
};
|
||||
|
||||
const NotificationMessage message_lcd_contrast_update = {
|
||||
.type = NotificationMessageTypeLcdContrastUpdate,
|
||||
};
|
||||
|
||||
/****************************** Message sequences ******************************/
|
||||
|
||||
// Reset
|
||||
@ -566,3 +570,8 @@ const NotificationSequence sequence_audiovisual_alert = {
|
||||
&message_vibro_off,
|
||||
NULL,
|
||||
};
|
||||
|
||||
const NotificationSequence sequence_lcd_contrast_update = {
|
||||
&message_lcd_contrast_update,
|
||||
NULL,
|
||||
};
|
||||
|
@ -63,6 +63,9 @@ extern const NotificationMessage message_force_vibro_setting_on;
|
||||
extern const NotificationMessage message_force_vibro_setting_off;
|
||||
extern const NotificationMessage message_force_display_brightness_setting_1f;
|
||||
|
||||
// LCD Messages
|
||||
extern const NotificationMessage message_lcd_contrast_update;
|
||||
|
||||
/****************************** Message sequences ******************************/
|
||||
|
||||
// Reset
|
||||
@ -138,6 +141,9 @@ extern const NotificationSequence sequence_success;
|
||||
extern const NotificationSequence sequence_error;
|
||||
extern const NotificationSequence sequence_audiovisual_alert;
|
||||
|
||||
// LCD
|
||||
extern const NotificationSequence sequence_lcd_contrast_update;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -20,6 +20,34 @@ static const NotificationSequence sequence_note_c = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
#define CONTRAST_COUNT 11
|
||||
const char* const contrast_text[CONTRAST_COUNT] = {
|
||||
"-5",
|
||||
"-4",
|
||||
"-3",
|
||||
"-2",
|
||||
"-1",
|
||||
"0",
|
||||
"+1",
|
||||
"+2",
|
||||
"+3",
|
||||
"+4",
|
||||
"+5",
|
||||
};
|
||||
const int32_t contrast_value[CONTRAST_COUNT] = {
|
||||
-5,
|
||||
-4,
|
||||
-3,
|
||||
-2,
|
||||
-1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
};
|
||||
|
||||
#define BACKLIGHT_COUNT 5
|
||||
const char* const backlight_text[BACKLIGHT_COUNT] = {
|
||||
"0%",
|
||||
@ -70,6 +98,15 @@ const char* const vibro_text[VIBRO_COUNT] = {
|
||||
};
|
||||
const bool vibro_value[VIBRO_COUNT] = {false, true};
|
||||
|
||||
static void contrast_changed(VariableItem* item) {
|
||||
NotificationAppSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, contrast_text[index]);
|
||||
app->notification->settings.contrast = contrast_value[index];
|
||||
notification_message(app->notification, &sequence_lcd_contrast_update);
|
||||
}
|
||||
|
||||
static void backlight_changed(VariableItem* item) {
|
||||
NotificationAppSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
@ -142,6 +179,13 @@ static NotificationAppSettings* alloc_settings() {
|
||||
VariableItem* item;
|
||||
uint8_t value_index;
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list, "LCD Contrast", CONTRAST_COUNT, contrast_changed, app);
|
||||
value_index =
|
||||
value_index_int32(app->notification->settings.contrast, contrast_value, CONTRAST_COUNT);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
||||
value_index = value_index_float(
|
||||
|
BIN
assets/dolphin/external/L2_Dj_128x64/frame_0.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_1.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_10.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_11.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_12.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_13.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_14.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_15.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_16.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_17.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_18.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_19.png
vendored
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_2.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_20.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_21.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_22.png
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_23.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_24.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_25.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_26.png
vendored
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_27.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_28.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_29.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_3.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_30.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_31.png
vendored
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_32.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_33.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_34.png
vendored
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_35.png
vendored
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_36.png
vendored
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_4.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_5.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_6.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_7.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_8.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/dolphin/external/L2_Dj_128x64/frame_9.png
vendored
Normal file
After Width: | Height: | Size: 1.6 KiB |
14
assets/dolphin/external/L2_Dj_128x64/meta.txt
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
Filetype: Flipper Animation
|
||||
Version: 1
|
||||
|
||||
Width: 128
|
||||
Height: 64
|
||||
Passive frames: 15
|
||||
Active frames: 23
|
||||
Frames order: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 26 28 29 30 31 32 33 34 35 36
|
||||
Active cycles: 1
|
||||
Frame rate: 2
|
||||
Duration: 3600
|
||||
Active cooldown: 5
|
||||
|
||||
Bubble slots: 0
|
7
assets/dolphin/external/manifest.txt
vendored
@ -127,6 +127,13 @@ Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Dj_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 2
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L3_Furippa3_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.7 KiB |
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,28.2,,
|
||||
Version,+,29.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -288,6 +288,8 @@ Function,+,__clear_cache,void,"void*, void*"
|
||||
Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*"
|
||||
Function,+,__errno,int*,
|
||||
Function,+,__furi_crash,void,
|
||||
Function,+,__furi_critical_enter,__FuriCriticalInfo,
|
||||
Function,+,__furi_critical_exit,void,__FuriCriticalInfo
|
||||
Function,+,__furi_halt,void,
|
||||
Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*"
|
||||
Function,-,__getline,ssize_t,"char**, size_t*, FILE*"
|
||||
@ -1999,6 +2001,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
@ -2259,6 +2262,7 @@ Variable,+,message_force_vibro_setting_off,const NotificationMessage,
|
||||
Variable,+,message_force_vibro_setting_on,const NotificationMessage,
|
||||
Variable,+,message_green_0,const NotificationMessage,
|
||||
Variable,+,message_green_255,const NotificationMessage,
|
||||
Variable,+,message_lcd_contrast_update,const NotificationMessage,
|
||||
Variable,+,message_note_a0,const NotificationMessage,
|
||||
Variable,+,message_note_a1,const NotificationMessage,
|
||||
Variable,+,message_note_a2,const NotificationMessage,
|
||||
@ -2402,6 +2406,7 @@ Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence,
|
||||
Variable,+,sequence_display_backlight_on,const NotificationSequence,
|
||||
Variable,+,sequence_double_vibro,const NotificationSequence,
|
||||
Variable,+,sequence_error,const NotificationSequence,
|
||||
Variable,+,sequence_lcd_contrast_update,const NotificationSequence,
|
||||
Variable,+,sequence_not_charging,const NotificationSequence,
|
||||
Variable,+,sequence_reset_blue,const NotificationSequence,
|
||||
Variable,+,sequence_reset_display,const NotificationSequence,
|
||||
|
|
@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,28.2,,
|
||||
Version,+,29.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@ -190,6 +190,7 @@ Header,+,lib/subghz/protocols/protocol_items.h,,
|
||||
Header,+,lib/subghz/protocols/raw.h,,
|
||||
Header,+,lib/subghz/receiver.h,,
|
||||
Header,+,lib/subghz/registry.h,,
|
||||
Header,+,lib/subghz/subghz_protocol_registry.h,,
|
||||
Header,+,lib/subghz/subghz_setting.h,,
|
||||
Header,+,lib/subghz/subghz_tx_rx_worker.h,,
|
||||
Header,+,lib/subghz/subghz_worker.h,,
|
||||
@ -324,6 +325,8 @@ Function,+,__errno,int*,
|
||||
Function,-,__fpclassifyd,int,double
|
||||
Function,-,__fpclassifyf,int,float
|
||||
Function,+,__furi_crash,void,
|
||||
Function,+,__furi_critical_enter,__FuriCriticalInfo,
|
||||
Function,+,__furi_critical_exit,void,__FuriCriticalInfo
|
||||
Function,+,__furi_halt,void,
|
||||
Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*"
|
||||
Function,-,__getline,ssize_t,"char**, size_t*, FILE*"
|
||||
@ -2715,13 +2718,13 @@ Function,+,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*
|
||||
Function,+,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_protocol_name_registry,const char*,"SubGhzEnvironment*, size_t"
|
||||
Function,+,subghz_environment_get_protocol_registry,void*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_protocol_registry,const SubGhzProtocolRegistry*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_reset_keeloq,void,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, void*"
|
||||
Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, const SubGhzProtocolRegistry*"
|
||||
Function,-,subghz_keystore_alloc,SubGhzKeystore*,
|
||||
Function,-,subghz_keystore_free,void,SubGhzKeystore*
|
||||
Function,-,subghz_keystore_get_data,SubGhzKeyArray_t*,SubGhzKeystore*
|
||||
@ -3515,6 +3518,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
@ -3795,6 +3799,7 @@ Variable,+,message_force_vibro_setting_off,const NotificationMessage,
|
||||
Variable,+,message_force_vibro_setting_on,const NotificationMessage,
|
||||
Variable,+,message_green_0,const NotificationMessage,
|
||||
Variable,+,message_green_255,const NotificationMessage,
|
||||
Variable,+,message_lcd_contrast_update,const NotificationMessage,
|
||||
Variable,+,message_note_a0,const NotificationMessage,
|
||||
Variable,+,message_note_a1,const NotificationMessage,
|
||||
Variable,+,message_note_a2,const NotificationMessage,
|
||||
@ -3938,6 +3943,7 @@ Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence,
|
||||
Variable,+,sequence_display_backlight_on,const NotificationSequence,
|
||||
Variable,+,sequence_double_vibro,const NotificationSequence,
|
||||
Variable,+,sequence_error,const NotificationSequence,
|
||||
Variable,+,sequence_lcd_contrast_update,const NotificationSequence,
|
||||
Variable,+,sequence_not_charging,const NotificationSequence,
|
||||
Variable,+,sequence_reset_blue,const NotificationSequence,
|
||||
Variable,+,sequence_reset_display,const NotificationSequence,
|
||||
@ -4062,27 +4068,6 @@ Variable,+,subghz_protocol_raw,const SubGhzProtocol,
|
||||
Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,+,subghz_protocol_registry,const SubGhzProtocolRegistry,
|
||||
Variable,-,subghz_protocol_scher_khan,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_scher_khan_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_scher_khan_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_secplus_v1,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_secplus_v1_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_secplus_v1_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_secplus_v2,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_secplus_v2_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_secplus_v2_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_smc5326,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_smc5326_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_smc5326_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_somfy_keytis,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_somfy_keytis_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_somfy_keytis_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_somfy_telis,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_somfy_telis_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_somfy_telis_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,subghz_protocol_star_line,const SubGhzProtocol,
|
||||
Variable,-,subghz_protocol_star_line_decoder,const SubGhzProtocolDecoder,
|
||||
Variable,-,subghz_protocol_star_line_encoder,const SubGhzProtocolEncoder,
|
||||
Variable,-,suboptarg,char*,
|
||||
Variable,+,usb_cdc_dual,FuriHalUsbInterface,
|
||||
Variable,+,usb_cdc_single,FuriHalUsbInterface,
|
||||
|
|
@ -3,6 +3,7 @@
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_bt.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
|
||||
#include <interface/patterns/ble_thread/shci/shci.h>
|
||||
#include <furi.h>
|
||||
@ -23,10 +24,10 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
// Device Info version
|
||||
if(sep == '.') {
|
||||
property_value_out(&property_context, NULL, 2, "format", "major", "3");
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "1");
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "2");
|
||||
} else {
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "major", "2");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "2");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "3");
|
||||
}
|
||||
|
||||
// Model name
|
||||
@ -297,6 +298,18 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
property_value_out(&property_context, NULL, 2, "radio", "alive", "false");
|
||||
}
|
||||
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
2,
|
||||
"system",
|
||||
"debug",
|
||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug));
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "system", "heap", "track", furi_hal_rtc_get_heap_track_mode());
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "system", "log", "level", furi_hal_rtc_get_log_level());
|
||||
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "protobuf", "version", "major", PROTOBUF_MAJOR_VERSION);
|
||||
property_context.last = true;
|
||||
|
@ -86,6 +86,7 @@ const GpioPinRecord gpio_pins[] = {
|
||||
/* Dangerous pins, may damage hardware */
|
||||
{.pin = &gpio_usart_rx, .name = "PB7", .debug = true},
|
||||
{.pin = &gpio_speaker, .name = "PB8", .debug = true},
|
||||
{.pin = &gpio_infrared_tx, .name = "PB9", .debug = true},
|
||||
};
|
||||
|
||||
const size_t gpio_pins_count = sizeof(gpio_pins) / sizeof(GpioPinRecord);
|
||||
|
@ -31,29 +31,22 @@ extern "C" {
|
||||
#define FURI_IS_ISR() (FURI_IS_IRQ_MODE() || FURI_IS_IRQ_MASKED())
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t isrm;
|
||||
bool from_isr;
|
||||
bool kernel_running;
|
||||
} __FuriCriticalInfo;
|
||||
|
||||
__FuriCriticalInfo __furi_critical_enter(void);
|
||||
|
||||
void __furi_critical_exit(__FuriCriticalInfo info);
|
||||
|
||||
#ifndef FURI_CRITICAL_ENTER
|
||||
#define FURI_CRITICAL_ENTER() \
|
||||
uint32_t __isrm = 0; \
|
||||
bool __from_isr = FURI_IS_ISR(); \
|
||||
bool __kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); \
|
||||
if(__from_isr) { \
|
||||
__isrm = taskENTER_CRITICAL_FROM_ISR(); \
|
||||
} else if(__kernel_running) { \
|
||||
taskENTER_CRITICAL(); \
|
||||
} else { \
|
||||
__disable_irq(); \
|
||||
}
|
||||
#define FURI_CRITICAL_ENTER() __FuriCriticalInfo __furi_critical_info = __furi_critical_enter();
|
||||
#endif
|
||||
|
||||
#ifndef FURI_CRITICAL_EXIT
|
||||
#define FURI_CRITICAL_EXIT() \
|
||||
if(__from_isr) { \
|
||||
taskEXIT_CRITICAL_FROM_ISR(__isrm); \
|
||||
} else if(__kernel_running) { \
|
||||
taskEXIT_CRITICAL(); \
|
||||
} else { \
|
||||
__enable_irq(); \
|
||||
}
|
||||
#define FURI_CRITICAL_EXIT() __furi_critical_exit(__furi_critical_info);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
29
furi/core/critical.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "common_defines.h"
|
||||
|
||||
__FuriCriticalInfo __furi_critical_enter(void) {
|
||||
__FuriCriticalInfo info;
|
||||
|
||||
info.isrm = 0;
|
||||
info.from_isr = FURI_IS_ISR();
|
||||
info.kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING);
|
||||
|
||||
if(info.from_isr) {
|
||||
info.isrm = taskENTER_CRITICAL_FROM_ISR();
|
||||
} else if(info.kernel_running) {
|
||||
taskENTER_CRITICAL();
|
||||
} else {
|
||||
__disable_irq();
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void __furi_critical_exit(__FuriCriticalInfo info) {
|
||||
if(info.from_isr) {
|
||||
taskEXIT_CRITICAL_FROM_ISR(info.isrm);
|
||||
} else if(info.kernel_running) {
|
||||
taskEXIT_CRITICAL();
|
||||
} else {
|
||||
__enable_irq();
|
||||
}
|
||||
}
|
@ -96,16 +96,17 @@ const char*
|
||||
|
||||
void subghz_environment_set_protocol_registry(
|
||||
SubGhzEnvironment* instance,
|
||||
void* protocol_registry_items) {
|
||||
const SubGhzProtocolRegistry* protocol_registry_items) {
|
||||
furi_assert(instance);
|
||||
const SubGhzProtocolRegistry* protocol_registry = protocol_registry_items;
|
||||
instance->protocol_registry = protocol_registry;
|
||||
}
|
||||
|
||||
void* subghz_environment_get_protocol_registry(SubGhzEnvironment* instance) {
|
||||
const SubGhzProtocolRegistry*
|
||||
subghz_environment_get_protocol_registry(SubGhzEnvironment* instance) {
|
||||
furi_assert(instance);
|
||||
furi_assert(instance->protocol_registry);
|
||||
return (void*)instance->protocol_registry;
|
||||
return instance->protocol_registry;
|
||||
}
|
||||
|
||||
const char*
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include "registry.h"
|
||||
|
||||
#include "subghz_keystore.h"
|
||||
|
||||
@ -9,6 +10,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SubGhzEnvironment SubGhzEnvironment;
|
||||
typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry;
|
||||
|
||||
/**
|
||||
* Allocate SubGhzEnvironment.
|
||||
@ -93,14 +95,15 @@ const char*
|
||||
*/
|
||||
void subghz_environment_set_protocol_registry(
|
||||
SubGhzEnvironment* instance,
|
||||
void* protocol_registry_items);
|
||||
const SubGhzProtocolRegistry* protocol_registry_items);
|
||||
|
||||
/**
|
||||
* Get list of protocols to work.
|
||||
* @param instance Pointer to a SubGhzEnvironment instance
|
||||
* @return Pointer to a SubGhzProtocolRegistry
|
||||
*/
|
||||
void* subghz_environment_get_protocol_registry(SubGhzEnvironment* instance);
|
||||
const SubGhzProtocolRegistry*
|
||||
subghz_environment_get_protocol_registry(SubGhzEnvironment* instance);
|
||||
|
||||
/**
|
||||
* Get list of protocols names.
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "../registry.h"
|
||||
#include "../subghz_protocol_registry.h"
|
||||
|
||||
#include "princeton.h"
|
||||
#include "keeloq.h"
|
||||
@ -43,13 +44,3 @@
|
||||
#include "alutech_at_4n.h"
|
||||
#include "kinggates_stylo_4k.h"
|
||||
#include "bin_raw.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SubGhzProtocolRegistry subghz_protocol_registry;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -9,6 +9,7 @@ extern "C" {
|
||||
typedef struct SubGhzEnvironment SubGhzEnvironment;
|
||||
|
||||
typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry;
|
||||
typedef struct SubGhzProtocol SubGhzProtocol;
|
||||
|
||||
struct SubGhzProtocolRegistry {
|
||||
const SubGhzProtocol** items;
|
||||
|
13
lib/subghz/subghz_protocol_registry.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "registry.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SubGhzProtocolRegistry subghz_protocol_registry;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -21,6 +21,9 @@
|
||||
#define SUBGHZ_RAW_FILE_VERSION 1
|
||||
#define SUBGHZ_RAW_FILE_TYPE "Flipper SubGhz RAW File"
|
||||
|
||||
typedef struct SubGhzProtocolRegistry SubGhzProtocolRegistry;
|
||||
typedef struct SubGhzEnvironment SubGhzEnvironment;
|
||||
|
||||
// Radio Preset
|
||||
typedef struct {
|
||||
FuriString* name;
|
||||
@ -116,11 +119,11 @@ typedef enum {
|
||||
SubGhzProtocolFlag_BinRAW = (1 << 10),
|
||||
} SubGhzProtocolFlag;
|
||||
|
||||
typedef struct {
|
||||
struct SubGhzProtocol {
|
||||
const char* name;
|
||||
SubGhzProtocolType type;
|
||||
SubGhzProtocolFlag flag;
|
||||
|
||||
const SubGhzProtocolEncoder* encoder;
|
||||
const SubGhzProtocolDecoder* decoder;
|
||||
} SubGhzProtocol;
|
||||
};
|
||||
|
@ -1,5 +1,18 @@
|
||||
#include "value_index.h"
|
||||
|
||||
uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count) {
|
||||
int64_t last_value = INT64_MIN;
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < values_count; i++) {
|
||||
if((value >= last_value) && (value <= values[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
last_value = values[i];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_t values_count) {
|
||||
int64_t last_value = INT64_MIN;
|
||||
uint8_t index = 0;
|
||||
|
@ -7,6 +7,19 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Get the index of a int32_t array element which is closest to the given value.
|
||||
*
|
||||
* Returned index corresponds to the first element found.
|
||||
* If no suitable elements were found, the function returns 0.
|
||||
*
|
||||
* @param value value to be searched.
|
||||
* @param values pointer to the array to perform the search in.
|
||||
* @param values_count array size.
|
||||
*
|
||||
* @return value's index.
|
||||
*/
|
||||
uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count);
|
||||
|
||||
/** Get the index of a uint32_t array element which is closest to the given value.
|
||||
*
|
||||
* Returned index corresponds to the first element found.
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define CONTRAST_ERC 32
|
||||
#define CONTRAST_MGG 31
|
||||
|
||||
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
UNUSED(u8x8);
|
||||
UNUSED(arg_ptr);
|
||||
@ -207,6 +210,19 @@ void u8x8_d_st756x_init(u8x8_t* u8x8, uint8_t contrast, uint8_t regulation_ratio
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
void u8x8_d_st756x_set_contrast(u8x8_t* u8x8, int8_t contrast_offset) {
|
||||
uint8_t contrast = (furi_hal_version_get_hw_display() == FuriHalVersionDisplayMgg) ?
|
||||
CONTRAST_MGG :
|
||||
CONTRAST_ERC;
|
||||
contrast += contrast_offset;
|
||||
contrast = contrast & 0b00111111;
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, ST756X_CMD_SET_EV);
|
||||
u8x8_cad_SendArg(u8x8, contrast);
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
/* call common procedure first and handle messages there */
|
||||
if(u8x8_d_st756x_common(u8x8, msg, arg_int, arg_ptr) == 0) {
|
||||
@ -225,7 +241,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void*
|
||||
* RR = 10 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.88 is 6 (0b110)
|
||||
* Bias = 1/9 (false)
|
||||
*/
|
||||
u8x8_d_st756x_init(u8x8, 31, 0b110, false);
|
||||
u8x8_d_st756x_init(u8x8, CONTRAST_MGG, 0b110, false);
|
||||
} else {
|
||||
/* ERC v1(ST7565) and v2(ST7567)
|
||||
* EV = 33
|
||||
@ -233,7 +249,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void*
|
||||
* RR = 9.3 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.47 is 5.5 (0b101)
|
||||
* Bias = 1/9 (false)
|
||||
*/
|
||||
u8x8_d_st756x_init(u8x8, 32, 0b101, false);
|
||||
u8x8_d_st756x_init(u8x8, CONTRAST_ERC, 0b101, false);
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
|
@ -14,3 +14,5 @@ void u8g2_Setup_st756x_flipper(
|
||||
u8x8_msg_cb gpio_and_delay_cb);
|
||||
|
||||
void u8x8_d_st756x_init(u8x8_t* u8x8, uint8_t contrast, uint8_t regulation_ratio, bool bias);
|
||||
|
||||
void u8x8_d_st756x_set_contrast(u8x8_t* u8x8, int8_t contrast_offset);
|
||||
|
@ -58,14 +58,23 @@ class Copro:
|
||||
def _getFileName(self, name):
|
||||
return posixpath.join(self.COPRO_TAR_DIR, name)
|
||||
|
||||
def _addFileReadPermission(self, tarinfo):
|
||||
tarinfo.mode = 0o644
|
||||
return tarinfo
|
||||
|
||||
def addFile(self, array, filename, **kwargs):
|
||||
source_file = os.path.join(self.mcu_copro, filename)
|
||||
self.output_tar.add(source_file, arcname=self._getFileName(filename))
|
||||
self.output_tar.add(
|
||||
source_file,
|
||||
arcname=self._getFileName(filename),
|
||||
filter=self._addFileReadPermission,
|
||||
)
|
||||
array.append({"name": filename, "sha256": file_sha256(source_file), **kwargs})
|
||||
|
||||
def bundle(self, output_file, stack_file_name, stack_type, stack_addr=None):
|
||||
self.output_tar = tarfile.open(output_file, "w:gz", format=tarfile.USTAR_FORMAT)
|
||||
fw_directory = tarfile.TarInfo(self.COPRO_TAR_DIR)
|
||||
fw_directory.mode = 0o755
|
||||
fw_directory.type = tarfile.DIRTYPE
|
||||
self.output_tar.addfile(fw_directory)
|
||||
|
||||
|
@ -46,7 +46,10 @@ class CoproFooterBase:
|
||||
_SIG_BIN_COMMON_SIZE = 2 * 4
|
||||
|
||||
def get_version(self):
|
||||
return f"Version {self.version_major}.{self.version_minor}.{self.version_sub}, branch {self.version_branch}, build {self.version_build} (magic {self.magic:X})"
|
||||
return (
|
||||
f"Version {self.version_major}.{self.version_minor}.{self.version_sub}, "
|
||||
f"branch {self.version_branch}, build {self.version_build} (magic {self.magic:X})"
|
||||
)
|
||||
|
||||
def get_details(self):
|
||||
raise CoproException("Not implemented")
|
||||
|
139
scripts/map_mariadb_insert.py
Executable file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Requiremets:
|
||||
# mariadb==1.1.6
|
||||
|
||||
from datetime import datetime
|
||||
import argparse
|
||||
import mariadb
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def parseArgs():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("db_user", help="MariaDB user")
|
||||
parser.add_argument("db_pass", help="MariaDB password")
|
||||
parser.add_argument("db_host", help="MariaDB hostname")
|
||||
parser.add_argument("db_port", type=int, help="MariaDB port")
|
||||
parser.add_argument("db_name", help="MariaDB database")
|
||||
parser.add_argument("report_file", help="Report file(.map.all)")
|
||||
args = parser.parse_args()
|
||||
return args
|
||||
|
||||
|
||||
def mariadbConnect(args):
|
||||
try:
|
||||
conn = mariadb.connect(
|
||||
user=args.db_user,
|
||||
password=args.db_pass,
|
||||
host=args.db_host,
|
||||
port=args.db_port,
|
||||
database=args.db_name,
|
||||
)
|
||||
except mariadb.Error as e:
|
||||
print(f"Error connecting to MariaDB: {e}")
|
||||
sys.exit(1)
|
||||
return conn
|
||||
|
||||
|
||||
def parseEnv():
|
||||
outArr = []
|
||||
outArr.append(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||||
outArr.append(os.getenv("COMMIT_HASH", default=None))
|
||||
outArr.append(os.getenv("COMMIT_MSG", default=None))
|
||||
outArr.append(os.getenv("BRANCH_NAME", default=None))
|
||||
outArr.append(os.getenv("BSS_SIZE", default=None))
|
||||
outArr.append(os.getenv("TEXT_SIZE", default=None))
|
||||
outArr.append(os.getenv("RODATA_SIZE", default=None))
|
||||
outArr.append(os.getenv("DATA_SIZE", default=None))
|
||||
outArr.append(os.getenv("FREE_FLASH_SIZE", default=None))
|
||||
outArr.append(os.getenv("PULL_ID", default=None))
|
||||
outArr.append(os.getenv("PULL_NAME", default=None))
|
||||
return outArr
|
||||
|
||||
|
||||
def createTables(cur, conn):
|
||||
headerTable = "CREATE TABLE IF NOT EXISTS `header` ( \
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, \
|
||||
`datetime` datetime NOT NULL, \
|
||||
`commit` varchar(40) NOT NULL, \
|
||||
`commit_msg` text NOT NULL, \
|
||||
`branch_name` text NOT NULL, \
|
||||
`bss_size` int(10) unsigned NOT NULL, \
|
||||
`text_size` int(10) unsigned NOT NULL, \
|
||||
`rodata_size` int(10) unsigned NOT NULL, \
|
||||
`data_size` int(10) unsigned NOT NULL, \
|
||||
`free_flash_size` int(10) unsigned NOT NULL, \
|
||||
`pullrequest_id` int(10) unsigned DEFAULT NULL, \
|
||||
`pullrequest_name` text DEFAULT NULL, \
|
||||
PRIMARY KEY (`id`), \
|
||||
KEY `header_id_index` (`id`) )"
|
||||
dataTable = "CREATE TABLE IF NOT EXISTS `data` ( \
|
||||
`header_id` int(10) unsigned NOT NULL, \
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, \
|
||||
`section` text NOT NULL, \
|
||||
`address` text NOT NULL, \
|
||||
`size` int(10) unsigned NOT NULL, \
|
||||
`name` text NOT NULL, \
|
||||
`lib` text NOT NULL, \
|
||||
`obj_name` text NOT NULL, \
|
||||
PRIMARY KEY (`id`), \
|
||||
KEY `data_id_index` (`id`), \
|
||||
KEY `data_header_id_index` (`header_id`), \
|
||||
CONSTRAINT `data_header_id_foreign` FOREIGN KEY (`header_id`) REFERENCES `header` (`id`) )"
|
||||
cur.execute(headerTable)
|
||||
cur.execute(dataTable)
|
||||
conn.commit()
|
||||
|
||||
|
||||
def insertHeader(data, cur, conn):
|
||||
query = "INSERT INTO `header` ( \
|
||||
datetime, commit, commit_msg, branch_name, bss_size, text_size, \
|
||||
rodata_size, data_size, free_flash_size, pullrequest_id, pullrequest_name) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
cur.execute(query, data)
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
|
||||
|
||||
def parseFile(fileObj, headerID):
|
||||
arr = []
|
||||
fileLines = fileObj.readlines()
|
||||
for line in fileLines:
|
||||
lineArr = []
|
||||
tempLineArr = line.split("\t")
|
||||
lineArr.append(headerID)
|
||||
lineArr.append(tempLineArr[0]) # section
|
||||
lineArr.append(int(tempLineArr[2], 16)) # address hex
|
||||
lineArr.append(int(tempLineArr[3])) # size
|
||||
lineArr.append(tempLineArr[4]) # name
|
||||
lineArr.append(tempLineArr[5]) # lib
|
||||
lineArr.append(tempLineArr[6]) # obj_name
|
||||
arr.append(tuple(lineArr))
|
||||
return arr
|
||||
|
||||
|
||||
def insertData(data, cur, conn):
|
||||
query = "INSERT INTO `data` ( \
|
||||
header_id, section, address, size, \
|
||||
name, lib, obj_name) \
|
||||
VALUES (?, ?, ?, ?, ? ,?, ?)"
|
||||
cur.executemany(query, data)
|
||||
conn.commit()
|
||||
|
||||
|
||||
def main():
|
||||
args = parseArgs()
|
||||
dbConn = mariadbConnect(args)
|
||||
reportFile = open(args.report_file)
|
||||
dbCurs = dbConn.cursor()
|
||||
createTables(dbCurs, dbConn)
|
||||
headerID = insertHeader(parseEnv(), dbCurs, dbConn)
|
||||
insertData(parseFile(reportFile, headerID), dbCurs, dbConn)
|
||||
reportFile.close()
|
||||
dbCurs.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
251
scripts/map_parser.py
Executable file
@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Requiremets:
|
||||
# cxxfilt==0.3.0
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
from typing import TextIO
|
||||
from cxxfilt import demangle
|
||||
|
||||
|
||||
class Objectfile:
|
||||
def __init__(self, section: str, offset: int, size: int, comment: str):
|
||||
self.section = section.strip()
|
||||
self.offset = offset
|
||||
self.size = size
|
||||
self.path = (None, None)
|
||||
self.basepath = None
|
||||
|
||||
if comment:
|
||||
self.path = re.match(r"^(.+?)(?:\(([^\)]+)\))?$", comment).groups()
|
||||
self.basepath = os.path.basename(self.path[0])
|
||||
|
||||
self.children = []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Objectfile {self.section} {self.offset:x} {self.size:x} {self.path} {repr(self.children)}>"
|
||||
|
||||
|
||||
def update_children_size(children: list[list], subsection_size: int) -> list:
|
||||
# set subsection size to an only child
|
||||
if len(children) == 1:
|
||||
children[0][1] = subsection_size
|
||||
return children
|
||||
|
||||
rest_size = subsection_size
|
||||
|
||||
for index in range(1, len(children)):
|
||||
if rest_size > 0:
|
||||
# current size = current address - previous child address
|
||||
child_size = children[index][0] - children[index - 1][0]
|
||||
rest_size -= child_size
|
||||
children[index - 1][1] = child_size
|
||||
|
||||
# if there is rest size, set it to the last child element
|
||||
if rest_size > 0:
|
||||
children[-1][1] = rest_size
|
||||
|
||||
return children
|
||||
|
||||
|
||||
def parse_sections(file_name: str) -> list:
|
||||
"""
|
||||
Quick&Dirty parsing for GNU ld’s linker map output, needs LANG=C, because
|
||||
some messages are localized.
|
||||
"""
|
||||
|
||||
sections = []
|
||||
with open(file_name, "r") as file:
|
||||
# skip until memory map is found
|
||||
found = False
|
||||
|
||||
while True:
|
||||
line = file.readline()
|
||||
if not line:
|
||||
break
|
||||
if line.strip() == "Memory Configuration":
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise Exception(f"Memory configuration is not found in the{input_file}")
|
||||
|
||||
# long section names result in a linebreak afterwards
|
||||
sectionre = re.compile(
|
||||
"(?P<section>.+?|.{14,}\n)[ ]+0x(?P<offset>[0-9a-f]+)[ ]+0x(?P<size>[0-9a-f]+)(?:[ ]+(?P<comment>.+))?\n+",
|
||||
re.I,
|
||||
)
|
||||
subsectionre = re.compile(
|
||||
"[ ]{16}0x(?P<offset>[0-9a-f]+)[ ]+(?P<function>.+)\n+", re.I
|
||||
)
|
||||
s = file.read()
|
||||
pos = 0
|
||||
|
||||
while True:
|
||||
m = sectionre.match(s, pos)
|
||||
if not m:
|
||||
# skip that line
|
||||
try:
|
||||
nextpos = s.index("\n", pos) + 1
|
||||
pos = nextpos
|
||||
continue
|
||||
except ValueError:
|
||||
break
|
||||
|
||||
pos = m.end()
|
||||
section = m.group("section")
|
||||
v = m.group("offset")
|
||||
offset = int(v, 16) if v is not None else None
|
||||
v = m.group("size")
|
||||
size = int(v, 16) if v is not None else None
|
||||
comment = m.group("comment")
|
||||
|
||||
if section != "*default*" and size > 0:
|
||||
of = Objectfile(section, offset, size, comment)
|
||||
|
||||
if section.startswith(" "):
|
||||
children = []
|
||||
sections[-1].children.append(of)
|
||||
|
||||
while True:
|
||||
m = subsectionre.match(s, pos)
|
||||
if not m:
|
||||
break
|
||||
pos = m.end()
|
||||
offset, function = m.groups()
|
||||
offset = int(offset, 16)
|
||||
if sections and sections[-1].children:
|
||||
children.append([offset, 0, function])
|
||||
|
||||
if children:
|
||||
children = update_children_size(
|
||||
children=children, subsection_size=of.size
|
||||
)
|
||||
|
||||
sections[-1].children[-1].children.extend(children)
|
||||
|
||||
else:
|
||||
sections.append(of)
|
||||
|
||||
return sections
|
||||
|
||||
|
||||
def get_subsection_name(section_name: str, subsection: Objectfile) -> str:
|
||||
subsection_split_names = subsection.section.split(".")
|
||||
if subsection.section.startswith("."):
|
||||
subsection_split_names = subsection_split_names[1:]
|
||||
|
||||
return (
|
||||
f".{subsection_split_names[1]}"
|
||||
if len(subsection_split_names) > 2
|
||||
else section_name
|
||||
)
|
||||
|
||||
|
||||
def write_subsection(
|
||||
section_name: str,
|
||||
subsection_name: str,
|
||||
address: str,
|
||||
size: int,
|
||||
demangled_name: str,
|
||||
module_name: str,
|
||||
file_name: str,
|
||||
mangled_name: str,
|
||||
write_file_object: TextIO,
|
||||
) -> None:
|
||||
write_file_object.write(
|
||||
f"{section_name}\t"
|
||||
f"{subsection_name}\t"
|
||||
f"{address}\t"
|
||||
f"{size}\t"
|
||||
f"{demangled_name}\t"
|
||||
f"{module_name}\t"
|
||||
f"{file_name}\t"
|
||||
f"{mangled_name}\n"
|
||||
)
|
||||
|
||||
|
||||
def save_subsection(
|
||||
section_name: str, subsection: Objectfile, write_file_object: TextIO
|
||||
) -> None:
|
||||
subsection_name = get_subsection_name(section_name, subsection)
|
||||
module_name = subsection.path[0]
|
||||
file_name = subsection.path[1]
|
||||
|
||||
if not file_name:
|
||||
file_name, module_name = module_name, ""
|
||||
|
||||
if not subsection.children:
|
||||
address = f"{subsection.offset:x}"
|
||||
size = subsection.size
|
||||
mangled_name = (
|
||||
""
|
||||
if subsection.section == section_name
|
||||
else subsection.section.split(".")[-1]
|
||||
)
|
||||
demangled_name = demangle(mangled_name) if mangled_name else mangled_name
|
||||
|
||||
write_subsection(
|
||||
section_name=section_name,
|
||||
subsection_name=subsection_name,
|
||||
address=address,
|
||||
size=size,
|
||||
demangled_name=demangled_name,
|
||||
module_name=module_name,
|
||||
file_name=file_name,
|
||||
mangled_name=mangled_name,
|
||||
write_file_object=write_file_object,
|
||||
)
|
||||
return
|
||||
|
||||
for subsection_child in subsection.children:
|
||||
address = f"{subsection_child[0]:x}"
|
||||
size = subsection_child[1]
|
||||
mangled_name = subsection_child[2]
|
||||
demangled_name = demangle(mangled_name)
|
||||
|
||||
write_subsection(
|
||||
section_name=section_name,
|
||||
subsection_name=subsection_name,
|
||||
address=address,
|
||||
size=size,
|
||||
demangled_name=demangled_name,
|
||||
module_name=module_name,
|
||||
file_name=file_name,
|
||||
mangled_name=mangled_name,
|
||||
write_file_object=write_file_object,
|
||||
)
|
||||
|
||||
|
||||
def save_section(section: Objectfile, write_file_object: TextIO) -> None:
|
||||
section_name = section.section
|
||||
for subsection in section.children:
|
||||
save_subsection(
|
||||
section_name=section_name,
|
||||
subsection=subsection,
|
||||
write_file_object=write_file_object,
|
||||
)
|
||||
|
||||
|
||||
def save_parsed_data(parsed_data: list[Objectfile], output_file_name: str) -> None:
|
||||
with open(output_file_name, "w") as write_file_object:
|
||||
for section in parsed_data:
|
||||
if section.children:
|
||||
save_section(section=section, write_file_object=write_file_object)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
raise Exception(f"Usage: {sys.argv[0]} <input file> <output file>")
|
||||
|
||||
input_file = sys.argv[1]
|
||||
output_file = sys.argv[2]
|
||||
|
||||
parsed_sections = parse_sections(input_file)
|
||||
|
||||
if parsed_sections is None:
|
||||
raise Exception(f"Memory configuration is not {input_file}")
|
||||
|
||||
save_parsed_data(parsed_sections, output_file)
|
@ -9,7 +9,7 @@ from flipper.utils.cdc import resolve_port
|
||||
def main():
|
||||
logger = logging.getLogger()
|
||||
if not (port := resolve_port(logger, "auto")):
|
||||
logger.error("Is Flipper connected over USB and is it not in DFU mode?")
|
||||
logger.error("Is Flipper connected via USB and not in DFU mode?")
|
||||
return 1
|
||||
subprocess.call(
|
||||
[
|
||||
|