mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
Merge branch 'dev' of https://github.com/DarkFlippers/unleashed-firmware into xfw-dev
This commit is contained in:
2
applications/external/doom/display.h
vendored
2
applications/external/doom/display.h
vendored
@@ -90,7 +90,7 @@ void drawVLine(uint8_t x, int8_t start_y, int8_t end_y, uint8_t intensity, Canva
|
||||
|
||||
void setupDisplay(Canvas* canvas) {
|
||||
memset(zbuffer, 0xff, 128);
|
||||
display_buf = (uint8_t*)canvas_get_buffer(canvas);
|
||||
display_buf = (uint8_t*)canvas->fb.tile_buf_ptr;
|
||||
//display_buf = u8g2_GetBufferPtr(&canvas->fb);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
//#include <notification/notification_messages.h>
|
||||
//#include <stdlib.h>
|
||||
|
||||
#include <u8g2.h>
|
||||
|
||||
#include "FlipperZeroWiFiDeauthModuleDefines.h"
|
||||
|
||||
#define DEAUTH_APP_DEBUG 0
|
||||
@@ -155,10 +153,8 @@ static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ct
|
||||
const char* strInitializing = "Something wrong";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strInitializing) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) /
|
||||
2) /* - (u8g2_GetMaxCharHeight(&canvas->fb) / 2)*/,
|
||||
(128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
|
||||
(64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
|
||||
strInitializing);
|
||||
} break;
|
||||
case WaitingForModule:
|
||||
@@ -171,10 +167,8 @@ static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ct
|
||||
const char* strInitializing = "Attach WiFi Deauther module";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strInitializing) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) /
|
||||
2) /* - (u8g2_GetMaxCharHeight(&canvas->fb) / 2)*/,
|
||||
(128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
|
||||
(64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
|
||||
strInitializing);
|
||||
}
|
||||
#endif
|
||||
@@ -189,18 +183,16 @@ static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ct
|
||||
const char* strInitializing = "Initializing...";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strInitializing) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) / 2) -
|
||||
(u8g2_GetMaxCharHeight(&canvas->fb) / 2),
|
||||
(128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
|
||||
(64 / 2) - (canvas_current_font_height(canvas) / 2),
|
||||
strInitializing);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_MODULE_POWER
|
||||
break;
|
||||
case ModuleActive: {
|
||||
uint8_t* buffer = canvas_get_buffer(canvas);
|
||||
app->m_canvasSize = canvas_get_buffer_size(canvas);
|
||||
uint8_t* buffer = canvas->fb.tile_buf_ptr;
|
||||
app->m_canvasSize = gui_get_framebuffer_size(app->m_gui);
|
||||
memcpy(buffer, app->m_backBuffer, app->m_canvasSize);
|
||||
} break;
|
||||
default:
|
||||
|
||||
@@ -74,11 +74,8 @@ static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) {
|
||||
static int32_t gps_uart_worker(void* context) {
|
||||
GpsUart* gps_uart = (GpsUart*)context;
|
||||
|
||||
gps_uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1);
|
||||
size_t rx_offset = 0;
|
||||
|
||||
gps_uart_serial_init(gps_uart);
|
||||
|
||||
while(1) {
|
||||
uint32_t events =
|
||||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
@@ -148,6 +145,8 @@ void gps_uart_init_thread(GpsUart* gps_uart) {
|
||||
gps_uart->status.time_minutes = 0;
|
||||
gps_uart->status.time_seconds = 0;
|
||||
|
||||
gps_uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1);
|
||||
|
||||
gps_uart->thread = furi_thread_alloc();
|
||||
furi_thread_set_name(gps_uart->thread, "GpsUartWorker");
|
||||
furi_thread_set_stack_size(gps_uart->thread, 1024);
|
||||
@@ -155,6 +154,8 @@ void gps_uart_init_thread(GpsUart* gps_uart) {
|
||||
furi_thread_set_callback(gps_uart->thread, gps_uart_worker);
|
||||
|
||||
furi_thread_start(gps_uart->thread);
|
||||
|
||||
gps_uart_serial_init(gps_uart);
|
||||
}
|
||||
|
||||
void gps_uart_deinit_thread(GpsUart* gps_uart) {
|
||||
|
||||
179
applications/external/subghz_remote/helpers/subrem_presets.c
vendored
Normal file
179
applications/external/subghz_remote/helpers/subrem_presets.c
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
#include "subrem_presets.h"
|
||||
|
||||
#define TAG "SubRemPresets"
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc() {
|
||||
SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset));
|
||||
|
||||
sub_preset->fff_data = flipper_format_string_alloc();
|
||||
sub_preset->file_path = furi_string_alloc();
|
||||
sub_preset->protocaol_name = furi_string_alloc();
|
||||
sub_preset->label = furi_string_alloc_set_str("N/A");
|
||||
|
||||
sub_preset->freq_preset.name = furi_string_alloc();
|
||||
|
||||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
sub_preset->load_state = SubRemLoadSubStateNotSet;
|
||||
|
||||
return sub_preset;
|
||||
}
|
||||
|
||||
void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(sub_preset);
|
||||
|
||||
furi_string_free(sub_preset->label);
|
||||
furi_string_free(sub_preset->protocaol_name);
|
||||
furi_string_free(sub_preset->file_path);
|
||||
flipper_format_free(sub_preset->fff_data);
|
||||
|
||||
furi_string_free(sub_preset->freq_preset.name);
|
||||
|
||||
free(sub_preset);
|
||||
}
|
||||
|
||||
void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(sub_preset);
|
||||
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
furi_string_reset(sub_preset->protocaol_name);
|
||||
furi_string_reset(sub_preset->file_path);
|
||||
|
||||
Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data);
|
||||
stream_clean(fff_data_stream);
|
||||
|
||||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
sub_preset->load_state = SubRemLoadSubStateNotSet;
|
||||
}
|
||||
|
||||
SubRemLoadSubState subrem_sub_preset_load(
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file) {
|
||||
furi_assert(sub_preset);
|
||||
furi_assert(txrx);
|
||||
furi_assert(fff_data_file);
|
||||
|
||||
Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data);
|
||||
|
||||
SubRemLoadSubState ret;
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
uint32_t repeat = 200;
|
||||
|
||||
ret = SubRemLoadSubStateError;
|
||||
|
||||
do {
|
||||
stream_clean(fff_data_stream);
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Type or version mismatch");
|
||||
break;
|
||||
}
|
||||
|
||||
SubGhzSetting* setting = subghz_txrx_get_setting(txrx); // txrx->setting;
|
||||
|
||||
//Load frequency or using default from settings
|
||||
ret = SubRemLoadSubStateErrorFreq;
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||
FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency");
|
||||
sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting);
|
||||
} else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) {
|
||||
FURI_LOG_E(TAG, "This frequency can only be used for RX");
|
||||
break;
|
||||
}
|
||||
sub_preset->freq_preset.frequency = temp_data32;
|
||||
|
||||
//Load preset
|
||||
ret = SubRemLoadSubStateErrorMod;
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set_str(
|
||||
temp_str, subghz_txrx_get_preset_name(txrx, furi_string_get_cstr(temp_str)));
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "")) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) {
|
||||
FURI_LOG_E(TAG, "CUSTOM preset is not supported");
|
||||
break;
|
||||
// TODO Custom preset loading logic if need
|
||||
// sub_preset->freq_preset.preset_index =
|
||||
// subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str));
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->freq_preset.name, temp_str);
|
||||
|
||||
// Load protocol
|
||||
ret = SubRemLoadSubStateErrorProtocol;
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperFormat* fff_data = sub_preset->fff_data;
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
|
||||
//if RAW
|
||||
subghz_protocol_raw_gen_fff_data(
|
||||
fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
stream_copy_full(
|
||||
flipper_format_get_raw_stream(fff_data_file),
|
||||
flipper_format_get_raw_stream(fff_data));
|
||||
}
|
||||
|
||||
if(subghz_txrx_load_decoder_by_name_protocol(txrx, furi_string_get_cstr(temp_str))) {
|
||||
SubGhzProtocolStatus status =
|
||||
subghz_protocol_decoder_base_deserialize(subghz_txrx_get_decoder(txrx), fff_data);
|
||||
if(status != SubGhzProtocolStatusOk) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol not found");
|
||||
break;
|
||||
}
|
||||
|
||||
const SubGhzProtocol* protocol = subghz_txrx_get_decoder(txrx)->protocol;
|
||||
|
||||
if(protocol->flag & SubGhzProtocolFlag_Send) {
|
||||
if((protocol->type == SubGhzProtocolTypeStatic) ||
|
||||
(protocol->type == SubGhzProtocolTypeDynamic) ||
|
||||
// TODO: BINRAW It probably works, but checks are needed.
|
||||
// (protocol->type == SubGhzProtocolTypeBinRAW) ||
|
||||
(protocol->type == SubGhzProtocolTypeRAW)) {
|
||||
sub_preset->type = protocol->type;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsuported Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->protocaol_name, temp_str);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol does not support transmission");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable Repeat");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = SubRemLoadSubStateOK;
|
||||
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label));
|
||||
#endif
|
||||
} while(false);
|
||||
|
||||
furi_string_free(temp_str);
|
||||
return ret;
|
||||
}
|
||||
38
applications/external/subghz_remote/helpers/subrem_presets.h
vendored
Normal file
38
applications/external/subghz_remote/helpers/subrem_presets.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "subrem_types.h"
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
#include "../../subghz/helpers/subghz_txrx.h"
|
||||
|
||||
typedef struct {
|
||||
FuriString* name;
|
||||
uint32_t frequency;
|
||||
// size_t preset_index; // Need for custom preset
|
||||
} FreqPreset;
|
||||
|
||||
// Sub File preset
|
||||
typedef struct {
|
||||
FlipperFormat* fff_data;
|
||||
FreqPreset freq_preset;
|
||||
FuriString* file_path;
|
||||
FuriString* protocaol_name;
|
||||
FuriString* label;
|
||||
SubGhzProtocolType type;
|
||||
SubRemLoadSubState load_state;
|
||||
} SubRemSubFilePreset;
|
||||
|
||||
typedef struct {
|
||||
SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount];
|
||||
} SubRemMapPreset;
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc();
|
||||
|
||||
void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset);
|
||||
|
||||
void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset);
|
||||
|
||||
SubRemLoadSubState subrem_sub_preset_load(
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file);
|
||||
@@ -25,8 +25,23 @@ typedef enum {
|
||||
SubRemViewIDRemote,
|
||||
} SubRemViewID;
|
||||
|
||||
typedef enum {
|
||||
SubRemLoadSubStateNotSet = 0,
|
||||
SubRemLoadSubStatePreloaded,
|
||||
SubRemLoadSubStateError,
|
||||
SubRemLoadSubStateErrorNoFile,
|
||||
SubRemLoadSubStateErrorFreq,
|
||||
SubRemLoadSubStateErrorMod,
|
||||
SubRemLoadSubStateErrorProtocol,
|
||||
SubRemLoadSubStateOK,
|
||||
} SubRemLoadSubState;
|
||||
|
||||
typedef enum {
|
||||
SubRemLoadMapStateBack = 0,
|
||||
SubRemLoadMapStateError,
|
||||
SubRemLoadMapStateErrorOpenError,
|
||||
SubRemLoadMapStateErrorStorage,
|
||||
SubRemLoadMapStateErrorBrokenFile,
|
||||
SubRemLoadMapStateNotAllOK,
|
||||
SubRemLoadMapStateOK,
|
||||
} SubRemLoadMapState;
|
||||
@@ -4,7 +4,8 @@ void subrem_scene_openmapfile_on_enter(void* context) {
|
||||
SubGhzRemoteApp* app = context;
|
||||
SubRemLoadMapState load_state = subrem_load_from_file(app);
|
||||
|
||||
if(load_state == SubRemLoadMapStateError) {
|
||||
if(load_state != SubRemLoadMapStateOK && load_state != SubRemLoadMapStateNotAllOK &&
|
||||
load_state != SubRemLoadMapStateBack) {
|
||||
#ifdef SUBREM_LIGHT
|
||||
dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file");
|
||||
#else
|
||||
@@ -18,7 +19,7 @@ void subrem_scene_openmapfile_on_enter(void* context) {
|
||||
dialog_message_free(message);
|
||||
#endif
|
||||
}
|
||||
if(load_state == SubRemLoadMapStateOK) {
|
||||
if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) {
|
||||
scene_manager_next_scene(app->scene_manager, SubRemSceneRemote);
|
||||
} else {
|
||||
// TODO: Map Preset Reset
|
||||
|
||||
@@ -37,17 +37,16 @@ static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) {
|
||||
|
||||
static bool subrem_scene_remote_update_data_show(void* context) {
|
||||
SubGhzRemoteApp* app = context;
|
||||
bool ret = false;
|
||||
|
||||
subrem_view_remote_add_data_to_show(
|
||||
app->subrem_remote_view,
|
||||
furi_string_get_cstr(app->subs_preset[0]->label),
|
||||
furi_string_get_cstr(app->subs_preset[1]->label),
|
||||
furi_string_get_cstr(app->subs_preset[2]->label),
|
||||
furi_string_get_cstr(app->subs_preset[3]->label),
|
||||
furi_string_get_cstr(app->subs_preset[4]->label));
|
||||
const char* labels[SubRemSubKeyNameMaxCount];
|
||||
|
||||
return ret;
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
labels[i] = furi_string_get_cstr(app->map_preset->subs_preset[i]->label);
|
||||
}
|
||||
|
||||
subrem_view_remote_add_data_to_show(app->subrem_remote_view, labels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subrem_scene_remote_on_enter(void* context) {
|
||||
@@ -81,32 +80,37 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) {
|
||||
event.event == SubRemCustomEventViewRemoteStartOK) {
|
||||
// Start sending sub
|
||||
subrem_tx_stop_sub(app, true);
|
||||
app->chusen_sub = subrem_scene_remote_event_to_index(event.event);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading);
|
||||
if(subrem_tx_start_sub(
|
||||
app,
|
||||
app->subs_preset[app->chusen_sub],
|
||||
subrem_scene_remote_raw_callback_end_tx)) {
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub);
|
||||
|
||||
uint8_t chusen_sub = subrem_scene_remote_event_to_index(event.event);
|
||||
app->chusen_sub = chusen_sub;
|
||||
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateLoading, chusen_sub);
|
||||
|
||||
if(subrem_tx_start_sub(app, app->map_preset->subs_preset[chusen_sub])) {
|
||||
if(app->map_preset->subs_preset[chusen_sub]->type == SubGhzProtocolTypeRAW) {
|
||||
subghz_txrx_set_raw_file_encoder_worker_callback_end(
|
||||
app->txrx, subrem_scene_remote_raw_callback_end_tx, app);
|
||||
}
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateSending);
|
||||
app->subrem_remote_view, SubRemViewRemoteStateSending, chusen_sub);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
} else {
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
return true;
|
||||
} else if(event.event == SubRemCustomEventViewRemoteForcedStop) {
|
||||
subrem_tx_stop_sub(app, true);
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
return true;
|
||||
} else if(event.event == SubRemCustomEventViewRemoteStop) {
|
||||
if(subrem_tx_stop_sub(app, false)) {
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(
|
||||
app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
@@ -123,8 +127,7 @@ void subrem_scene_remote_on_exit(void* context) {
|
||||
|
||||
subrem_tx_stop_sub(app, true);
|
||||
|
||||
subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle);
|
||||
subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,10 @@ void subrem_scene_start_on_enter(void* context) {
|
||||
// subrem_scene_start_submenu_callback,
|
||||
// app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart));
|
||||
// TODO: set scene state in subrem alloc
|
||||
// submenu_set_selected_item(
|
||||
// submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart));
|
||||
submenu_set_selected_item(submenu, SubmenuIndexSubRemOpenMapFile);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,14 @@ static void subghz_remote_app_tick_event_callback(void* context) {
|
||||
SubGhzRemoteApp* subghz_remote_app_alloc() {
|
||||
SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp));
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_common_migrate(storage, EXT_PATH("subghz/unirf"), SUBREM_APP_FOLDER);
|
||||
|
||||
if(!storage_simply_mkdir(storage, SUBREM_APP_FOLDER)) {
|
||||
//FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER);
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
// Enable power for External CC1101 if it is connected
|
||||
furi_hal_subghz_enable_ext_power();
|
||||
// Auto switch to internal radio if external radio is not available
|
||||
@@ -43,6 +51,7 @@ SubGhzRemoteApp* subghz_remote_app_alloc() {
|
||||
|
||||
// View Dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
|
||||
app->scene_manager = scene_manager_alloc(&subrem_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
@@ -74,27 +83,14 @@ SubGhzRemoteApp* subghz_remote_app_alloc() {
|
||||
SubRemViewIDRemote,
|
||||
subrem_view_remote_get_view(app->subrem_remote_view));
|
||||
|
||||
app->map_preset = malloc(sizeof(SubRemMapPreset));
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
app->subs_preset[i] = subrem_sub_file_preset_alloc();
|
||||
app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc();
|
||||
}
|
||||
|
||||
app->setting = subghz_setting_alloc();
|
||||
subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user"));
|
||||
app->txrx = subghz_txrx_alloc();
|
||||
|
||||
app->environment = subghz_environment_alloc();
|
||||
|
||||
subghz_environment_load_keystore(app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes"));
|
||||
subghz_environment_load_keystore(
|
||||
app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user"));
|
||||
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/came_atomo"));
|
||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/alutech_at_4n"));
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
app->environment, EXT_PATH("subghz/assets/nice_flor_s"));
|
||||
subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry);
|
||||
|
||||
app->receiver = subghz_receiver_alloc_init(app->environment);
|
||||
subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app);
|
||||
|
||||
app->tx_running = false;
|
||||
|
||||
@@ -128,13 +124,15 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) {
|
||||
view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote);
|
||||
subrem_view_remote_free(app->subrem_remote_view);
|
||||
|
||||
subghz_receiver_free(app->receiver);
|
||||
subghz_environment_free(app->environment);
|
||||
subghz_setting_free(app->setting);
|
||||
scene_manager_free(app->scene_manager);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
subghz_txrx_free(app->txrx);
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
subrem_sub_file_preset_free(app->subs_preset[i]);
|
||||
subrem_sub_file_preset_free(app->map_preset->subs_preset[i]);
|
||||
}
|
||||
free(app->map_preset);
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <lib/subghz/protocols/protocol_items.h>
|
||||
|
||||
#include "../subghz/helpers/subghz_txrx_i.h"
|
||||
|
||||
// #include <lib/subghz/protocols/keeloq.h>
|
||||
// #include <lib/subghz/protocols/star_line.h>
|
||||
|
||||
@@ -11,6 +13,12 @@
|
||||
|
||||
#define TAG "SubGhzRemote"
|
||||
|
||||
// XXX Using TxRx
|
||||
// [x] use TxRx preset subrem_sub_preset_load & subrem_tx_start_sub
|
||||
// [x] subrem_sub_preset_load & drop subrem_set_preset_data
|
||||
// [x] subrem_tx_start_sub
|
||||
// [x] subrem_tx_stop_sub
|
||||
|
||||
static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = {
|
||||
[SubRemSubKeyNameUp] = {"UP", "ULABEL"},
|
||||
[SubRemSubKeyNameDown] = {"DOWN", "DLABEL"},
|
||||
@@ -19,80 +27,69 @@ static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = {
|
||||
[SubRemSubKeyNameOk] = {"OK", "OKLABEL"},
|
||||
};
|
||||
|
||||
static bool
|
||||
subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) {
|
||||
const char* preset_name = "";
|
||||
if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) {
|
||||
preset_name = "AM270";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) {
|
||||
preset_name = "AM650";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) {
|
||||
preset_name = "FM238";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) {
|
||||
preset_name = "FM476";
|
||||
} else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) {
|
||||
// preset_name = "CUSTOM";
|
||||
return false;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unknown preset");
|
||||
return false;
|
||||
}
|
||||
size_t preset_index = subghz_setting_get_inx_preset_by_name(setting, preset_name);
|
||||
freq_preset->data = subghz_setting_get_preset_data(setting, preset_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc() {
|
||||
SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset));
|
||||
|
||||
sub_preset->fff_data = flipper_format_string_alloc();
|
||||
sub_preset->file_path = furi_string_alloc();
|
||||
sub_preset->protocaol_name = furi_string_alloc();
|
||||
sub_preset->label = furi_string_alloc_set_str("N/A");
|
||||
|
||||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
|
||||
return sub_preset;
|
||||
}
|
||||
|
||||
void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(sub_preset);
|
||||
|
||||
furi_string_free(sub_preset->label);
|
||||
furi_string_free(sub_preset->protocaol_name);
|
||||
furi_string_free(sub_preset->file_path);
|
||||
flipper_format_free(sub_preset->fff_data);
|
||||
|
||||
free(sub_preset);
|
||||
}
|
||||
|
||||
static void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(sub_preset);
|
||||
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
furi_string_reset(sub_preset->protocaol_name);
|
||||
furi_string_reset(sub_preset->file_path);
|
||||
|
||||
Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data);
|
||||
stream_clean(fff_data_stream);
|
||||
|
||||
sub_preset->type = SubGhzProtocolTypeUnknown;
|
||||
}
|
||||
|
||||
void subrem_map_preset_reset(SubGhzRemoteApp* app) {
|
||||
furi_assert(app);
|
||||
static void subrem_map_preset_reset(SubRemMapPreset* map_preset) {
|
||||
furi_assert(map_preset);
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
subrem_sub_file_preset_reset(app->subs_preset[i]);
|
||||
subrem_sub_file_preset_reset(map_preset->subs_preset[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) {
|
||||
furi_assert(app);
|
||||
static SubRemLoadMapState subrem_map_preset_check(
|
||||
SubRemMapPreset* map_preset,
|
||||
SubGhzTxRx* txrx,
|
||||
FlipperFormat* fff_data_file) {
|
||||
furi_assert(map_preset);
|
||||
furi_assert(txrx);
|
||||
|
||||
bool all_loaded = true;
|
||||
SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile;
|
||||
|
||||
SubRemLoadSubState sub_preset_loaded;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = map_preset->subs_preset[i];
|
||||
|
||||
sub_preset_loaded = SubRemLoadSubStateErrorNoFile;
|
||||
|
||||
if(furi_string_empty(sub_preset->file_path)) {
|
||||
// FURI_LOG_I(TAG, "Empty file path");
|
||||
} else if(!flipper_format_file_open_existing(
|
||||
fff_data_file, furi_string_get_cstr(sub_preset->file_path))) {
|
||||
FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
sub_preset_loaded = subrem_sub_preset_load(sub_preset, txrx, fff_data_file);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// Load file state logic
|
||||
// Label depending on the state
|
||||
// Move to remote scene
|
||||
|
||||
if(sub_preset_loaded != SubRemLoadSubStateOK) {
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
all_loaded = false;
|
||||
} else {
|
||||
ret = SubRemLoadMapStateNotAllOK;
|
||||
}
|
||||
|
||||
if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) {
|
||||
ret = SubRemLoadMapStateOK;
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* fff_data_file) {
|
||||
furi_assert(map_preset);
|
||||
bool ret = false;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = app->subs_preset[i];
|
||||
sub_preset = map_preset->subs_preset[i];
|
||||
if(!flipper_format_read_string(
|
||||
fff_data_file, map_file_labels[i][0], sub_preset->file_path)) {
|
||||
#if FURI_DEBUG
|
||||
@@ -106,55 +103,119 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]);
|
||||
#endif
|
||||
// TODO move to remote scene
|
||||
path_extract_filename(sub_preset->file_path, sub_preset->label, true);
|
||||
ret = true;
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
if(ret) {
|
||||
// Preload seccesful
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"%-5s: %s %s",
|
||||
map_file_labels[i][0],
|
||||
furi_string_get_cstr(sub_preset->label),
|
||||
furi_string_get_cstr(sub_preset->file_path));
|
||||
ret = true;
|
||||
sub_preset->load_state = SubRemLoadSubStatePreloaded;
|
||||
}
|
||||
|
||||
flipper_format_rewind(fff_data_file);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) {
|
||||
SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) {
|
||||
furi_assert(app);
|
||||
furi_assert(file_path);
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Load Map File Start");
|
||||
#endif
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
SubRemLoadMapState ret = SubRemLoadMapStateErrorOpenError;
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Open Map File..");
|
||||
#endif
|
||||
subrem_map_preset_reset(app->map_preset);
|
||||
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Could not open MAP file %s", file_path);
|
||||
ret = SubRemLoadMapStateErrorOpenError;
|
||||
} else {
|
||||
if(!subrem_map_preset_load(app->map_preset, fff_data_file)) {
|
||||
FURI_LOG_E(TAG, "Could no Sub file path in MAP file");
|
||||
// ret = // error for popup
|
||||
} else if(!flipper_format_file_close(fff_data_file)) {
|
||||
ret = SubRemLoadMapStateErrorOpenError;
|
||||
} else {
|
||||
ret = subrem_map_preset_check(app->map_preset, app->txrx, fff_data_file);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == SubRemLoadMapStateOK) {
|
||||
FURI_LOG_I(TAG, "Load Map File Seccesful");
|
||||
} else if(ret == SubRemLoadMapStateNotAllOK) {
|
||||
FURI_LOG_I(TAG, "Load Map File Seccesful [Not all files]");
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Broken Map File");
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
flipper_format_free(fff_data_file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* sub_file_name) {
|
||||
furi_assert(flipper_format);
|
||||
furi_assert(dev_file_name);
|
||||
furi_assert(sub_file_name);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format);
|
||||
|
||||
bool saved = false;
|
||||
uint32_t repeat = 200;
|
||||
FuriString* file_dir = furi_string_alloc();
|
||||
|
||||
path_extract_dirname(dev_file_name, file_dir);
|
||||
path_extract_dirname(sub_file_name, file_dir);
|
||||
do {
|
||||
//removing additional fields
|
||||
// removing additional fields
|
||||
flipper_format_delete_key(flipper_format, "Repeat");
|
||||
//flipper_format_delete_key(flipper_format, "Manufacture");
|
||||
// flipper_format_delete_key(flipper_format, "Manufacture");
|
||||
|
||||
if(!storage_simply_remove(storage, dev_file_name)) {
|
||||
if(!storage_simply_remove(storage, sub_file_name)) {
|
||||
break;
|
||||
}
|
||||
|
||||
//ToDo check Write
|
||||
stream_seek(flipper_format_stream, 0, StreamOffsetFromStart);
|
||||
stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS);
|
||||
stream_save_to_file(flipper_format_stream, storage, sub_file_name, FSOM_CREATE_ALWAYS);
|
||||
|
||||
if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
|
||||
FURI_LOG_E(TAG, "Unable Repeat");
|
||||
break;
|
||||
}
|
||||
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
furi_string_free(file_dir);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool subrem_tx_start_sub(
|
||||
SubGhzRemoteApp* app,
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzProtocolEncoderRAWCallbackEnd callback) {
|
||||
void subrem_save_active_sub(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzRemoteApp* app = context;
|
||||
|
||||
SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub];
|
||||
subrem_save_protocol_to_file(
|
||||
sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
}
|
||||
|
||||
bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) {
|
||||
furi_assert(app);
|
||||
furi_assert(sub_preset);
|
||||
bool ret = false;
|
||||
@@ -162,88 +223,44 @@ bool subrem_tx_start_sub(
|
||||
subrem_tx_stop_sub(app, true);
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeUnknown) {
|
||||
return false;
|
||||
}
|
||||
ret = false;
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label));
|
||||
|
||||
FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label));
|
||||
subghz_txrx_load_decoder_by_name_protocol(
|
||||
app->txrx, furi_string_get_cstr(sub_preset->protocaol_name));
|
||||
|
||||
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
||||
keeloq_reset_original_btn();
|
||||
subghz_custom_btns_reset();
|
||||
subghz_txrx_set_preset(
|
||||
app->txrx,
|
||||
furi_string_get_cstr(sub_preset->freq_preset.name),
|
||||
sub_preset->freq_preset.frequency,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
do {
|
||||
flipper_format_rewind(sub_preset->fff_data); //
|
||||
|
||||
app->transmitter = subghz_transmitter_alloc_init(
|
||||
app->environment, furi_string_get_cstr(sub_preset->protocaol_name));
|
||||
|
||||
if(app->transmitter) {
|
||||
if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) !=
|
||||
SubGhzProtocolStatusOk) {
|
||||
FURI_LOG_E(TAG, "Deserialize error!");
|
||||
break;
|
||||
}
|
||||
furi_hal_subghz_reset();
|
||||
furi_hal_subghz_idle();
|
||||
furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_hal_subghz_idle();
|
||||
|
||||
furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency);
|
||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false);
|
||||
furi_hal_gpio_init(
|
||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
if(!furi_hal_subghz_tx()) {
|
||||
FURI_LOG_E(TAG, "Sending not allowed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeRAW) {
|
||||
subghz_protocol_raw_file_encoder_worker_set_callback_end(
|
||||
(SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(
|
||||
app->transmitter),
|
||||
callback,
|
||||
app);
|
||||
}
|
||||
|
||||
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter);
|
||||
subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK);
|
||||
keeloq_reset_original_btn();
|
||||
subghz_custom_btns_reset();
|
||||
|
||||
if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) {
|
||||
ret = true;
|
||||
}
|
||||
} while(false);
|
||||
}
|
||||
|
||||
app->tx_running = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void subghz_tx_stop(SubGhzRemoteApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
//Stop TX
|
||||
furi_hal_subghz_stop_async_tx();
|
||||
|
||||
subghz_transmitter_stop(app->transmitter);
|
||||
subghz_transmitter_free(app->transmitter);
|
||||
furi_hal_subghz_idle();
|
||||
}
|
||||
|
||||
bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) {
|
||||
furi_assert(app);
|
||||
SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub];
|
||||
SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub];
|
||||
|
||||
if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) {
|
||||
// SubRemSubKeyTypeRawKey)) {
|
||||
// XXX drop app->tx_running
|
||||
if(app->tx_running) {
|
||||
subghz_tx_stop(app);
|
||||
subghz_txrx_stop(app->txrx);
|
||||
|
||||
if(sub_preset->type == SubGhzProtocolTypeDynamic) {
|
||||
subrem_save_protocol_to_file(
|
||||
sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
|
||||
keeloq_reset_mfname();
|
||||
keeloq_reset_kl_type();
|
||||
keeloq_reset_original_btn();
|
||||
@@ -260,170 +277,6 @@ bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) {
|
||||
furi_assert(app);
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
bool ret = false;
|
||||
bool sub_preset_loaded = false;
|
||||
SubRemSubFilePreset* sub_preset;
|
||||
|
||||
for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) {
|
||||
sub_preset = app->subs_preset[i];
|
||||
sub_preset_loaded = false;
|
||||
if(furi_string_empty(sub_preset->file_path)) {
|
||||
// FURI_LOG_I(TAG, "Empty file path");
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(
|
||||
fff_data_file, furi_string_get_cstr(sub_preset->file_path))) {
|
||||
FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Type or version mismatch");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load frequency
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||
FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency");
|
||||
sub_preset->freq_preset.frequency =
|
||||
subghz_setting_get_default_frequency(app->setting);
|
||||
} else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) {
|
||||
FURI_LOG_E(TAG, "This frequency can only be used for RX");
|
||||
break;
|
||||
} else {
|
||||
sub_preset->freq_preset.frequency = temp_data32;
|
||||
}
|
||||
|
||||
//Load preset
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Preset");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subrem_set_preset_data(
|
||||
app->setting, &sub_preset->freq_preset, furi_string_get_cstr(temp_str))) {
|
||||
FURI_LOG_E(TAG, "Cannot load preset.");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load protocol
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
FURI_LOG_E(TAG, "Missing Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
FlipperFormat* fff_data = sub_preset->fff_data;
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
|
||||
//if RAW
|
||||
subghz_protocol_raw_gen_fff_data(
|
||||
fff_data, furi_string_get_cstr(sub_preset->file_path));
|
||||
} else {
|
||||
stream_copy_full(
|
||||
flipper_format_get_raw_stream(fff_data_file),
|
||||
flipper_format_get_raw_stream(fff_data));
|
||||
}
|
||||
|
||||
const SubGhzProtocolRegistry* protocol_registry_items =
|
||||
subghz_environment_get_protocol_registry(app->environment);
|
||||
|
||||
const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name(
|
||||
protocol_registry_items, furi_string_get_cstr(temp_str));
|
||||
|
||||
if(!protocol) {
|
||||
FURI_LOG_E(TAG, "Protocol not found");
|
||||
break;
|
||||
} else if(protocol->flag & SubGhzProtocolFlag_Send) {
|
||||
if((protocol->type == SubGhzProtocolTypeStatic) ||
|
||||
(protocol->type == SubGhzProtocolTypeDynamic) ||
|
||||
// (protocol->type == SubGhzProtocolTypeBinRAW) || // TODO: BINRAW
|
||||
(protocol->type == SubGhzProtocolTypeRAW)) {
|
||||
sub_preset->type = protocol->type;
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Unsuported Protocol");
|
||||
break;
|
||||
}
|
||||
|
||||
furi_string_set(sub_preset->protocaol_name, temp_str);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Protocol does not support transmission");
|
||||
}
|
||||
|
||||
sub_preset_loaded = true;
|
||||
ret |= true;
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label));
|
||||
#endif
|
||||
} while(false);
|
||||
|
||||
// TODO:
|
||||
// Load file state logic
|
||||
// Label depending on the state
|
||||
|
||||
if(!sub_preset_loaded) {
|
||||
furi_string_set_str(sub_preset->label, "N/A");
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
}
|
||||
furi_string_free(temp_str);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) {
|
||||
furi_assert(app);
|
||||
furi_assert(file_path);
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Load Map File Start");
|
||||
#endif
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
bool ret = false;
|
||||
#if FURI_DEBUG
|
||||
FURI_LOG_I(TAG, "Open Map File..");
|
||||
#endif
|
||||
subrem_map_preset_reset(app);
|
||||
|
||||
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||
FURI_LOG_E(TAG, "Could not open MAP file %s", file_path);
|
||||
} else {
|
||||
if(!subrem_map_preset_load(app, fff_data_file)) {
|
||||
FURI_LOG_E(TAG, "Could no Sub file path in MAP file");
|
||||
// ret = // error for popup
|
||||
} else if(
|
||||
(flipper_format_file_close(fff_data_file)) &&
|
||||
(subrem_map_preset_check(app, fff_data_file))) {
|
||||
FURI_LOG_I(TAG, "Load Map File Seccesful");
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Popup for error or return error type
|
||||
if(!ret) {
|
||||
FURI_LOG_E(TAG, "Broken Map File");
|
||||
}
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
flipper_format_free(fff_data_file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
@@ -436,10 +289,8 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) {
|
||||
|
||||
// Input events and views are managed by file_select
|
||||
if(!dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) {
|
||||
} else if(subrem_map_file_load(app, furi_string_get_cstr(app->file_path))) {
|
||||
ret = SubRemLoadMapStateOK;
|
||||
} else {
|
||||
ret = SubRemLoadMapStateError;
|
||||
ret = subrem_map_file_load(app, furi_string_get_cstr(app->file_path));
|
||||
}
|
||||
|
||||
furi_string_free(file_path);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/subrem_types.h"
|
||||
#include "helpers/subrem_presets.h"
|
||||
|
||||
#include "../subghz/helpers/subghz_txrx.h"
|
||||
|
||||
#include <assets_icons.h>
|
||||
|
||||
#include "views/remote.h"
|
||||
@@ -29,25 +33,6 @@
|
||||
#define SUBREM_APP_FOLDER EXT_PATH("subghz/remote")
|
||||
#define SUBREM_MAX_LEN_NAME 64
|
||||
|
||||
typedef struct {
|
||||
uint32_t frequency;
|
||||
uint8_t* data;
|
||||
} FreqPreset;
|
||||
|
||||
// Sub File preset
|
||||
typedef struct {
|
||||
FlipperFormat* fff_data;
|
||||
FreqPreset freq_preset;
|
||||
FuriString* file_path;
|
||||
FuriString* protocaol_name;
|
||||
FuriString* label;
|
||||
SubGhzProtocolType type;
|
||||
} SubRemSubFilePreset;
|
||||
|
||||
SubRemSubFilePreset* subrem_sub_file_preset_alloc();
|
||||
|
||||
void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset);
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
@@ -55,30 +40,25 @@ typedef struct {
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
Submenu* submenu;
|
||||
|
||||
FuriString* file_path;
|
||||
char file_name_tmp[SUBREM_MAX_LEN_NAME];
|
||||
// char file_name_tmp[SUBREM_MAX_LEN_NAME];
|
||||
|
||||
SubRemViewRemote* subrem_remote_view;
|
||||
|
||||
SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount];
|
||||
SubRemMapPreset* map_preset;
|
||||
|
||||
SubGhzSetting* setting;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzTransmitter* transmitter;
|
||||
SubGhzTxRx* txrx;
|
||||
|
||||
bool tx_running;
|
||||
|
||||
uint8_t chusen_sub;
|
||||
|
||||
// TODO: LoadFileError
|
||||
} SubGhzRemoteApp;
|
||||
|
||||
SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app);
|
||||
|
||||
bool subrem_tx_start_sub(
|
||||
SubGhzRemoteApp* app,
|
||||
SubRemSubFilePreset* sub_preset,
|
||||
SubGhzProtocolEncoderRAWCallbackEnd callback);
|
||||
bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset);
|
||||
|
||||
bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced);
|
||||
|
||||
void subrem_save_active_sub(void* context);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 16
|
||||
#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 12
|
||||
|
||||
struct SubRemViewRemote {
|
||||
View* view;
|
||||
@@ -41,24 +41,18 @@ void subrem_view_remote_set_callback(
|
||||
subrem_view_remote->context = context;
|
||||
}
|
||||
|
||||
void subrem_view_remote_add_data_to_show(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
const char* up_label,
|
||||
const char* down_label,
|
||||
const char* left_label,
|
||||
const char* right_label,
|
||||
const char* ok_label) {
|
||||
void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels) {
|
||||
furi_assert(subrem_view_remote);
|
||||
|
||||
with_view_model(
|
||||
subrem_view_remote->view,
|
||||
SubRemViewRemoteModel * model,
|
||||
{
|
||||
strncpy(model->up_label, up_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->down_label, down_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->left_label, left_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->up_label, labels[0], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->down_label, labels[1], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->left_label, labels[2], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->right_label, labels[3], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
strncpy(model->ok_label, labels[4], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH);
|
||||
|
||||
// furi_string_set(model->up_label, up_label);
|
||||
// furi_string_set(model->down_label, down_label);
|
||||
@@ -69,23 +63,21 @@ void subrem_view_remote_add_data_to_show(
|
||||
true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn) {
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state,
|
||||
uint8_t presed_btn) {
|
||||
furi_assert(subrem_view_remote);
|
||||
with_view_model(
|
||||
subrem_view_remote->view,
|
||||
SubRemViewRemoteModel * model,
|
||||
{ model->pressed_btn = presed_btn; },
|
||||
{
|
||||
model->state = state;
|
||||
model->pressed_btn = presed_btn;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state) {
|
||||
furi_assert(subrem_view_remote);
|
||||
with_view_model(
|
||||
subrem_view_remote->view, SubRemViewRemoteModel * model, { model->state = state; }, true);
|
||||
}
|
||||
|
||||
void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
@@ -24,15 +24,9 @@ void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote);
|
||||
|
||||
View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote);
|
||||
|
||||
void subrem_view_remote_add_data_to_show(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
const char* up_label,
|
||||
const char* down_label,
|
||||
const char* left_label,
|
||||
const char* right_label,
|
||||
const char* ok_label);
|
||||
void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels);
|
||||
|
||||
void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn);
|
||||
void subrem_view_remote_set_state(
|
||||
SubRemViewRemote* subrem_view_remote,
|
||||
SubRemViewRemoteState state);
|
||||
SubRemViewRemoteState state,
|
||||
uint8_t presed_btn);
|
||||
@@ -366,11 +366,8 @@ int32_t tetris_game_app() {
|
||||
|
||||
// Not doing this eventually causes issues with TimerSvc due to not sleeping/yielding enough in this task
|
||||
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
|
||||
TaskHandle_t curr_task = xTaskGetHandle("Tetris Game");
|
||||
|
||||
uint32_t origTimerPrio = uxTaskPriorityGet(timer_task);
|
||||
uint32_t myPrio = uxTaskPriorityGet(curr_task);
|
||||
vTaskPrioritySet(timer_task, myPrio + 1);
|
||||
vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_set_orientation(view_port, ViewPortOrientationVertical);
|
||||
@@ -471,7 +468,7 @@ int32_t tetris_game_app() {
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_mutex_free(tetris_state->mutex);
|
||||
vTaskPrioritySet(timer_task, origTimerPrio);
|
||||
vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
|
||||
free(newPiece);
|
||||
free(tetris_state);
|
||||
|
||||
|
||||
BIN
applications/external/wifi_marauder_companion/assets/KeyKeyboardSelected_10x11.png
vendored
Normal file
BIN
applications/external/wifi_marauder_companion/assets/KeyKeyboardSelected_10x11.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
applications/external/wifi_marauder_companion/assets/KeyKeyboard_10x11.png
vendored
Normal file
BIN
applications/external/wifi_marauder_companion/assets/KeyKeyboard_10x11.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.6 KiB |
@@ -12,3 +12,4 @@ ADD_SCENE(wifi_marauder, script_confirm_delete, ScriptConfirmDelete)
|
||||
ADD_SCENE(wifi_marauder, script_stage_edit, ScriptStageEdit)
|
||||
ADD_SCENE(wifi_marauder, script_stage_add, ScriptStageAdd)
|
||||
ADD_SCENE(wifi_marauder, script_stage_edit_list, ScriptStageEditList)
|
||||
ADD_SCENE(wifi_marauder, sniffpmkid_options, SniffPmkidOptions)
|
||||
|
||||
117
applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_sniffpmkid_options.c
vendored
Normal file
117
applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_sniffpmkid_options.c
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
#include "../wifi_marauder_app_i.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexPassive,
|
||||
SubmenuIndexActive,
|
||||
SubmenuIndexTargetedPassive,
|
||||
SubmenuIndexTargetedActive,
|
||||
SubmenuIndexChannelPassive,
|
||||
SubmenuIndexChannelActive,
|
||||
};
|
||||
|
||||
static void wifi_marauder_scene_sniffpmkid_options_callback(void* context, uint32_t index) {
|
||||
WifiMarauderApp* app = context;
|
||||
|
||||
app->is_custom_tx_string = false; // this will be set if needed by text input
|
||||
switch(index) {
|
||||
case SubmenuIndexPassive:
|
||||
app->selected_tx_string = "sniffpmkid";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
|
||||
break;
|
||||
case SubmenuIndexActive:
|
||||
app->selected_tx_string = "sniffpmkid -d";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
|
||||
break;
|
||||
case SubmenuIndexTargetedPassive:
|
||||
app->selected_tx_string = "sniffpmkid -l";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
|
||||
break;
|
||||
case SubmenuIndexTargetedActive:
|
||||
app->selected_tx_string = "sniffpmkid -d -l";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneConsoleOutput);
|
||||
break;
|
||||
case SubmenuIndexChannelPassive:
|
||||
app->selected_tx_string = "sniffpmkid -c";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput);
|
||||
break;
|
||||
case SubmenuIndexChannelActive:
|
||||
app->selected_tx_string = "sniffpmkid -d -c";
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneSniffPmkidOptions, index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneTextInput);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_marauder_scene_sniffpmkid_options_on_enter(void* context) {
|
||||
WifiMarauderApp* app = context;
|
||||
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_set_header(submenu, "Sniff PMKID");
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Passive",
|
||||
SubmenuIndexPassive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Active (Force Deauth)",
|
||||
SubmenuIndexActive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Targeted Passive (List)",
|
||||
SubmenuIndexTargetedPassive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Targeted Active (List)",
|
||||
SubmenuIndexTargetedActive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"On Channel # - Passive",
|
||||
SubmenuIndexChannelPassive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"On Channel # - Active",
|
||||
SubmenuIndexChannelActive,
|
||||
wifi_marauder_scene_sniffpmkid_options_callback,
|
||||
app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu,
|
||||
scene_manager_get_scene_state(app->scene_manager, WifiMarauderSceneSniffPmkidOptions));
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, WifiMarauderAppViewSubmenu);
|
||||
}
|
||||
|
||||
bool wifi_marauder_scene_sniffpmkid_options_on_event(void* context, SceneManagerEvent event) {
|
||||
//WifiMarauderApp* app = context;
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void wifi_marauder_scene_sniffpmkid_options_on_exit(void* context) {
|
||||
WifiMarauderApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
@@ -97,13 +97,6 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = {
|
||||
NO_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Sniff PMKID",
|
||||
{"ap", "channel"},
|
||||
2,
|
||||
{"sniffpmkid -d -l", "sniffpmkid -c"},
|
||||
TOGGLE_ARGS,
|
||||
FOCUS_CONSOLE_END,
|
||||
SHOW_STOPSCAN_TIP},
|
||||
{"Channel",
|
||||
{"get", "set"},
|
||||
2,
|
||||
@@ -161,6 +154,14 @@ static void wifi_marauder_scene_start_var_list_enter_callback(void* context, uin
|
||||
return;
|
||||
}
|
||||
|
||||
if(app->selected_tx_string &&
|
||||
strncmp("sniffpmkid", app->selected_tx_string, strlen("sniffpmkid")) == 0) {
|
||||
// sniffpmkid submenu
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, WifiMarauderEventStartSniffPmkidOptions);
|
||||
return;
|
||||
}
|
||||
|
||||
// Select automation script
|
||||
if(index == NUM_MENU_ITEMS - 2) {
|
||||
view_dispatcher_send_custom_event(
|
||||
@@ -254,6 +255,10 @@ bool wifi_marauder_scene_start_on_event(void* context, SceneManagerEvent event)
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneScriptSelect);
|
||||
} else if(event.event == WifiMarauderEventStartSniffPmkidOptions) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, WifiMarauderSceneStart, app->selected_menu_index);
|
||||
scene_manager_next_scene(app->scene_manager, WifiMarauderSceneSniffPmkidOptions);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WIFI_MARAUDER_APP_VERSION "v0.3.5"
|
||||
#define WIFI_MARAUDER_APP_VERSION "v0.3.6"
|
||||
|
||||
typedef struct WifiMarauderApp WifiMarauderApp;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#define NUM_MENU_ITEMS (18)
|
||||
#define NUM_MENU_ITEMS (17)
|
||||
|
||||
#define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096)
|
||||
#define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512)
|
||||
|
||||
@@ -8,5 +8,6 @@ typedef enum {
|
||||
WifiMarauderEventSaveDestinationMac,
|
||||
WifiMarauderEventStartSettingsInit,
|
||||
WifiMarauderEventStartLogViewer,
|
||||
WifiMarauderEventStartScriptSelect
|
||||
WifiMarauderEventStartScriptSelect,
|
||||
WifiMarauderEventStartSniffPmkidOptions
|
||||
} WifiMarauderCustomEvent;
|
||||
|
||||
@@ -15,149 +15,215 @@ typedef struct {
|
||||
const uint8_t y;
|
||||
} WIFI_TextInputKey;
|
||||
|
||||
typedef struct {
|
||||
const WIFI_TextInputKey* rows[3];
|
||||
const uint8_t keyboard_index;
|
||||
} Keyboard;
|
||||
|
||||
typedef struct {
|
||||
const char* header;
|
||||
char* text_buffer;
|
||||
size_t text_buffer_size;
|
||||
size_t minimum_length;
|
||||
bool clear_default_text;
|
||||
|
||||
bool cursor_select;
|
||||
size_t cursor_pos;
|
||||
|
||||
WIFI_TextInputCallback callback;
|
||||
void* callback_context;
|
||||
|
||||
uint8_t selected_row;
|
||||
uint8_t selected_column;
|
||||
uint8_t selected_keyboard;
|
||||
|
||||
WIFI_TextInputValidatorCallback validator_callback;
|
||||
void* validator_callback_context;
|
||||
FuriString* validator_text;
|
||||
bool valadator_message_visible;
|
||||
bool validator_message_visible;
|
||||
} WIFI_TextInputModel;
|
||||
|
||||
static const uint8_t keyboard_origin_x = 1;
|
||||
static const uint8_t keyboard_origin_y = 29;
|
||||
static const uint8_t keyboard_row_count = 4;
|
||||
static const uint8_t keyboard_row_count = 3;
|
||||
static const uint8_t keyboard_count = 2;
|
||||
|
||||
#define ENTER_KEY '\r'
|
||||
#define BACKSPACE_KEY '\b'
|
||||
#define SWITCH_KEYBOARD_KEY 0xfe
|
||||
|
||||
static const WIFI_TextInputKey keyboard_keys_row_1[] = {
|
||||
{'{', 1, 0},
|
||||
{'(', 9, 0},
|
||||
{'[', 17, 0},
|
||||
{'|', 25, 0},
|
||||
{'@', 33, 0},
|
||||
{'&', 41, 0},
|
||||
{'#', 49, 0},
|
||||
{';', 57, 0},
|
||||
{'^', 65, 0},
|
||||
{'*', 73, 0},
|
||||
{'`', 81, 0},
|
||||
{'"', 89, 0},
|
||||
{'~', 97, 0},
|
||||
{'\'', 105, 0},
|
||||
{'.', 113, 0},
|
||||
{'/', 120, 0},
|
||||
{'q', 1, 8},
|
||||
{'w', 10, 8},
|
||||
{'e', 19, 8},
|
||||
{'r', 28, 8},
|
||||
{'t', 37, 8},
|
||||
{'y', 46, 8},
|
||||
{'u', 55, 8},
|
||||
{'i', 64, 8},
|
||||
{'o', 73, 8},
|
||||
{'p', 82, 8},
|
||||
{'0', 91, 8},
|
||||
{'1', 100, 8},
|
||||
{'2', 110, 8},
|
||||
{'3', 120, 8},
|
||||
};
|
||||
|
||||
static const WIFI_TextInputKey keyboard_keys_row_2[] = {
|
||||
{'q', 1, 10},
|
||||
{'w', 9, 10},
|
||||
{'e', 17, 10},
|
||||
{'r', 25, 10},
|
||||
{'t', 33, 10},
|
||||
{'y', 41, 10},
|
||||
{'u', 49, 10},
|
||||
{'i', 57, 10},
|
||||
{'o', 65, 10},
|
||||
{'p', 73, 10},
|
||||
{'0', 81, 10},
|
||||
{'1', 89, 10},
|
||||
{'2', 97, 10},
|
||||
{'3', 105, 10},
|
||||
{'=', 113, 10},
|
||||
{'-', 120, 10},
|
||||
{'a', 1, 20},
|
||||
{'s', 10, 20},
|
||||
{'d', 19, 20},
|
||||
{'f', 28, 20},
|
||||
{'g', 37, 20},
|
||||
{'h', 46, 20},
|
||||
{'j', 55, 20},
|
||||
{'k', 64, 20},
|
||||
{'l', 73, 20},
|
||||
{BACKSPACE_KEY, 82, 12},
|
||||
{'4', 100, 20},
|
||||
{'5', 110, 20},
|
||||
{'6', 120, 20},
|
||||
};
|
||||
|
||||
static const WIFI_TextInputKey keyboard_keys_row_3[] = {
|
||||
{'a', 1, 21},
|
||||
{'s', 9, 21},
|
||||
{'d', 18, 21},
|
||||
{'f', 25, 21},
|
||||
{'g', 33, 21},
|
||||
{'h', 41, 21},
|
||||
{'j', 49, 21},
|
||||
{'k', 57, 21},
|
||||
{'l', 65, 21},
|
||||
{BACKSPACE_KEY, 72, 13},
|
||||
{'4', 89, 21},
|
||||
{'5', 97, 21},
|
||||
{'6', 105, 21},
|
||||
{'$', 113, 21},
|
||||
{'%', 120, 21},
|
||||
|
||||
{SWITCH_KEYBOARD_KEY, 1, 23},
|
||||
{'z', 13, 32},
|
||||
{'x', 21, 32},
|
||||
{'c', 28, 32},
|
||||
{'v', 36, 32},
|
||||
{'b', 44, 32},
|
||||
{'n', 52, 32},
|
||||
{'m', 59, 32},
|
||||
{'_', 67, 32},
|
||||
{ENTER_KEY, 74, 23},
|
||||
{'7', 100, 32},
|
||||
{'8', 110, 32},
|
||||
{'9', 120, 32},
|
||||
};
|
||||
|
||||
static const WIFI_TextInputKey keyboard_keys_row_4[] = {
|
||||
{'z', 1, 33},
|
||||
{'x', 9, 33},
|
||||
{'c', 18, 33},
|
||||
{'v', 25, 33},
|
||||
{'b', 33, 33},
|
||||
{'n', 41, 33},
|
||||
{'m', 49, 33},
|
||||
{'_', 57, 33},
|
||||
{ENTER_KEY, 64, 24},
|
||||
{'7', 89, 33},
|
||||
{'8', 97, 33},
|
||||
{'9', 105, 33},
|
||||
{'!', 113, 33},
|
||||
{'+', 120, 33},
|
||||
static const WIFI_TextInputKey symbol_keyboard_keys_row_1[] = {
|
||||
{'!', 2, 8},
|
||||
{'@', 12, 8},
|
||||
{'#', 22, 8},
|
||||
{'$', 32, 8},
|
||||
{'%', 42, 8},
|
||||
{'^', 52, 8},
|
||||
{'&', 62, 8},
|
||||
{'(', 71, 8},
|
||||
{')', 81, 8},
|
||||
{'0', 91, 8},
|
||||
{'1', 100, 8},
|
||||
{'2', 110, 8},
|
||||
{'3', 120, 8},
|
||||
};
|
||||
|
||||
static uint8_t get_row_size(uint8_t row_index) {
|
||||
static const WIFI_TextInputKey symbol_keyboard_keys_row_2[] = {
|
||||
{'~', 2, 20},
|
||||
{'+', 12, 20},
|
||||
{'-', 22, 20},
|
||||
{'=', 32, 20},
|
||||
{'[', 42, 20},
|
||||
{']', 52, 20},
|
||||
{'{', 62, 20},
|
||||
{'}', 72, 20},
|
||||
{BACKSPACE_KEY, 82, 12},
|
||||
{'4', 100, 20},
|
||||
{'5', 110, 20},
|
||||
{'6', 120, 20},
|
||||
};
|
||||
|
||||
static const WIFI_TextInputKey symbol_keyboard_keys_row_3[] = {
|
||||
{SWITCH_KEYBOARD_KEY, 1, 23},
|
||||
{'.', 15, 32},
|
||||
{',', 29, 32},
|
||||
{';', 41, 32},
|
||||
{'`', 53, 32},
|
||||
{'\'', 65, 32},
|
||||
{ENTER_KEY, 74, 23},
|
||||
{'7', 100, 32},
|
||||
{'8', 110, 32},
|
||||
{'9', 120, 32},
|
||||
};
|
||||
|
||||
static const Keyboard keyboard = {
|
||||
.rows =
|
||||
{
|
||||
keyboard_keys_row_1,
|
||||
keyboard_keys_row_2,
|
||||
keyboard_keys_row_3,
|
||||
},
|
||||
.keyboard_index = 0,
|
||||
};
|
||||
|
||||
static const Keyboard symbol_keyboard = {
|
||||
.rows =
|
||||
{
|
||||
symbol_keyboard_keys_row_1,
|
||||
symbol_keyboard_keys_row_2,
|
||||
symbol_keyboard_keys_row_3,
|
||||
},
|
||||
.keyboard_index = 1,
|
||||
};
|
||||
|
||||
static const Keyboard* keyboards[] = {
|
||||
&keyboard,
|
||||
&symbol_keyboard,
|
||||
};
|
||||
|
||||
static void switch_keyboard(WIFI_TextInputModel* model) {
|
||||
model->selected_keyboard = (model->selected_keyboard + 1) % keyboard_count;
|
||||
}
|
||||
|
||||
static uint8_t get_row_size(const Keyboard* keyboard, uint8_t row_index) {
|
||||
uint8_t row_size = 0;
|
||||
|
||||
switch(row_index + 1) {
|
||||
case 1:
|
||||
row_size = sizeof(keyboard_keys_row_1) / sizeof(WIFI_TextInputKey);
|
||||
break;
|
||||
case 2:
|
||||
row_size = sizeof(keyboard_keys_row_2) / sizeof(WIFI_TextInputKey);
|
||||
break;
|
||||
case 3:
|
||||
row_size = sizeof(keyboard_keys_row_3) / sizeof(WIFI_TextInputKey);
|
||||
break;
|
||||
case 4:
|
||||
row_size = sizeof(keyboard_keys_row_4) / sizeof(WIFI_TextInputKey);
|
||||
break;
|
||||
if(keyboard == &symbol_keyboard) {
|
||||
switch(row_index + 1) {
|
||||
case 1:
|
||||
row_size = COUNT_OF(symbol_keyboard_keys_row_1);
|
||||
break;
|
||||
case 2:
|
||||
row_size = COUNT_OF(symbol_keyboard_keys_row_2);
|
||||
break;
|
||||
case 3:
|
||||
row_size = COUNT_OF(symbol_keyboard_keys_row_3);
|
||||
break;
|
||||
default:
|
||||
furi_crash(NULL);
|
||||
}
|
||||
} else {
|
||||
switch(row_index + 1) {
|
||||
case 1:
|
||||
row_size = COUNT_OF(keyboard_keys_row_1);
|
||||
break;
|
||||
case 2:
|
||||
row_size = COUNT_OF(keyboard_keys_row_2);
|
||||
break;
|
||||
case 3:
|
||||
row_size = COUNT_OF(keyboard_keys_row_3);
|
||||
break;
|
||||
default:
|
||||
furi_crash(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return row_size;
|
||||
}
|
||||
|
||||
static const WIFI_TextInputKey* get_row(uint8_t row_index) {
|
||||
static const WIFI_TextInputKey* get_row(const Keyboard* keyboard, uint8_t row_index) {
|
||||
const WIFI_TextInputKey* row = NULL;
|
||||
|
||||
switch(row_index + 1) {
|
||||
case 1:
|
||||
row = keyboard_keys_row_1;
|
||||
break;
|
||||
case 2:
|
||||
row = keyboard_keys_row_2;
|
||||
break;
|
||||
case 3:
|
||||
row = keyboard_keys_row_3;
|
||||
break;
|
||||
case 4:
|
||||
row = keyboard_keys_row_4;
|
||||
break;
|
||||
if(row_index < 3) {
|
||||
row = keyboard->rows[row_index];
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
static char get_selected_char(WIFI_TextInputModel* model) {
|
||||
return get_row(model->selected_row)[model->selected_column].text;
|
||||
return get_row(
|
||||
keyboards[model->selected_keyboard], model->selected_row)[model->selected_column]
|
||||
.text;
|
||||
}
|
||||
|
||||
static bool char_is_lowercase(char letter) {
|
||||
@@ -165,27 +231,9 @@ static bool char_is_lowercase(char letter) {
|
||||
}
|
||||
|
||||
static char char_to_uppercase(const char letter) {
|
||||
switch(letter) {
|
||||
case '_':
|
||||
if(letter == '_') {
|
||||
return 0x20;
|
||||
case '(':
|
||||
return 0x29;
|
||||
case '{':
|
||||
return 0x7d;
|
||||
case '[':
|
||||
return 0x5d;
|
||||
case '/':
|
||||
return 0x5c;
|
||||
case ';':
|
||||
return 0x3a;
|
||||
case '.':
|
||||
return 0x2c;
|
||||
case '!':
|
||||
return 0x3f;
|
||||
case '<':
|
||||
return 0x3e;
|
||||
}
|
||||
if(char_is_lowercase(letter)) {
|
||||
} else if(char_is_lowercase(letter)) {
|
||||
return (letter - 0x20);
|
||||
} else {
|
||||
return letter;
|
||||
@@ -193,86 +241,96 @@ static char char_to_uppercase(const char letter) {
|
||||
}
|
||||
|
||||
static void wifi_text_input_backspace_cb(WIFI_TextInputModel* model) {
|
||||
uint8_t text_length = model->clear_default_text ? 1 : strlen(model->text_buffer);
|
||||
if(text_length > 0) {
|
||||
model->text_buffer[text_length - 1] = 0;
|
||||
if(model->clear_default_text) {
|
||||
model->text_buffer[0] = 0;
|
||||
model->cursor_pos = 0;
|
||||
} else if(model->cursor_pos > 0) {
|
||||
char* move = model->text_buffer + model->cursor_pos;
|
||||
memmove(move - 1, move, strlen(move) + 1);
|
||||
model->cursor_pos--;
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
WIFI_TextInputModel* model = _model;
|
||||
//uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
|
||||
uint8_t text_length = model->text_buffer ? strlen(model->text_buffer) : 0;
|
||||
uint8_t needed_string_width = canvas_width(canvas) - 8;
|
||||
uint8_t start_pos = 4;
|
||||
|
||||
const char* text = model->text_buffer;
|
||||
model->cursor_pos = model->cursor_pos > text_length ? text_length : model->cursor_pos;
|
||||
size_t cursor_pos = model->cursor_pos;
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
canvas_draw_str(canvas, 2, 7, model->header);
|
||||
elements_slightly_rounded_frame(canvas, 1, 8, 126, 12);
|
||||
canvas_draw_str(canvas, 2, 8, model->header);
|
||||
elements_slightly_rounded_frame(canvas, 1, 12, 126, 15);
|
||||
|
||||
if(canvas_string_width(canvas, text) > needed_string_width) {
|
||||
canvas_draw_str(canvas, start_pos, 17, "...");
|
||||
start_pos += 6;
|
||||
needed_string_width -= 8;
|
||||
}
|
||||
|
||||
while(text != 0 && canvas_string_width(canvas, text) > needed_string_width) {
|
||||
text++;
|
||||
char buf[model->text_buffer_size + 1];
|
||||
if(model->text_buffer) {
|
||||
strlcpy(buf, model->text_buffer, sizeof(buf));
|
||||
}
|
||||
char* str = buf;
|
||||
|
||||
if(model->clear_default_text) {
|
||||
elements_slightly_rounded_box(
|
||||
canvas, start_pos - 1, 14, canvas_string_width(canvas, text) + 2, 10);
|
||||
canvas, start_pos - 1, 14, canvas_string_width(canvas, str) + 2, 10);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else {
|
||||
canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 1, 18, "|");
|
||||
canvas_draw_str(canvas, start_pos + canvas_string_width(canvas, text) + 2, 18, "|");
|
||||
char* move = str + cursor_pos;
|
||||
memmove(move + 1, move, strlen(move) + 1);
|
||||
str[cursor_pos] = '|';
|
||||
}
|
||||
canvas_draw_str(canvas, start_pos, 17, text);
|
||||
|
||||
if(cursor_pos > 0 && canvas_string_width(canvas, str) > needed_string_width) {
|
||||
canvas_draw_str(canvas, start_pos, 22, "...");
|
||||
start_pos += 6;
|
||||
needed_string_width -= 8;
|
||||
for(uint32_t off = 0;
|
||||
strlen(str) && canvas_string_width(canvas, str) > needed_string_width &&
|
||||
off < cursor_pos;
|
||||
off++) {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
if(canvas_string_width(canvas, str) > needed_string_width) {
|
||||
needed_string_width -= 4;
|
||||
size_t len = strlen(str);
|
||||
while(len && canvas_string_width(canvas, str) > needed_string_width) {
|
||||
str[len--] = '\0';
|
||||
}
|
||||
strcat(str, "...");
|
||||
}
|
||||
|
||||
canvas_draw_str(canvas, start_pos, 22, str);
|
||||
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
|
||||
for(uint8_t row = 0; row <= keyboard_row_count; row++) {
|
||||
const uint8_t column_count = get_row_size(row);
|
||||
const WIFI_TextInputKey* keys = get_row(row);
|
||||
for(uint8_t row = 0; row < keyboard_row_count; row++) {
|
||||
const uint8_t column_count = get_row_size(keyboards[model->selected_keyboard], row);
|
||||
const WIFI_TextInputKey* keys = get_row(keyboards[model->selected_keyboard], row);
|
||||
|
||||
for(size_t column = 0; column < column_count; column++) {
|
||||
bool selected = !model->cursor_select && model->selected_row == row &&
|
||||
model->selected_column == column;
|
||||
const Icon* icon = NULL;
|
||||
if(keys[column].text == ENTER_KEY) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(model->selected_row == row && model->selected_column == column) {
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
&I_KeySaveSelected_24x11);
|
||||
} else {
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
&I_KeySave_24x11);
|
||||
}
|
||||
icon = selected ? &I_KeySaveSelected_24x11 : &I_KeySave_24x11;
|
||||
} else if(keys[column].text == SWITCH_KEYBOARD_KEY) {
|
||||
icon = selected ? &I_KeyKeyboardSelected_10x11 : &I_KeyKeyboard_10x11;
|
||||
} else if(keys[column].text == BACKSPACE_KEY) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(model->selected_row == row && model->selected_column == column) {
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
&I_KeyBackspaceSelected_16x9);
|
||||
} else {
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
&I_KeyBackspace_16x9);
|
||||
}
|
||||
icon = selected ? &I_KeyBackspaceSelected_16x9 : &I_KeyBackspace_16x9;
|
||||
}
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(icon != NULL) {
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
icon);
|
||||
} else {
|
||||
if(model->selected_row == row && model->selected_column == column) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
if(selected) {
|
||||
canvas_draw_box(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x - 1,
|
||||
@@ -280,19 +338,25 @@ static void wifi_text_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
7,
|
||||
10);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
keys[column].text);
|
||||
if(model->clear_default_text || text_length == 0) {
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
char_to_uppercase(keys[column].text));
|
||||
} else {
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
keys[column].text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(model->valadator_message_visible) {
|
||||
if(model->validator_message_visible) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
canvas_draw_box(canvas, 8, 10, 110, 48);
|
||||
@@ -310,37 +374,69 @@ static void
|
||||
UNUSED(wifi_text_input);
|
||||
if(model->selected_row > 0) {
|
||||
model->selected_row--;
|
||||
if(model->selected_column > get_row_size(model->selected_row) - 6) {
|
||||
if(model->selected_row == 0 &&
|
||||
model->selected_column >
|
||||
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 6) {
|
||||
model->selected_column = model->selected_column + 1;
|
||||
}
|
||||
if(model->selected_row == 1 &&
|
||||
model->selected_keyboard == symbol_keyboard.keyboard_index) {
|
||||
if(model->selected_column > 5)
|
||||
model->selected_column += 2;
|
||||
else if(model->selected_column > 1)
|
||||
model->selected_column += 1;
|
||||
}
|
||||
} else {
|
||||
model->cursor_select = true;
|
||||
model->clear_default_text = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wifi_text_input_handle_down(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
|
||||
UNUSED(wifi_text_input);
|
||||
if(model->selected_row < keyboard_row_count - 1) {
|
||||
if(model->cursor_select) {
|
||||
model->cursor_select = false;
|
||||
} else if(model->selected_row < keyboard_row_count - 1) {
|
||||
model->selected_row++;
|
||||
if(model->selected_column > get_row_size(model->selected_row) - 4) {
|
||||
if(model->selected_row == 1 &&
|
||||
model->selected_column >
|
||||
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 4) {
|
||||
model->selected_column = model->selected_column - 1;
|
||||
}
|
||||
if(model->selected_row == 2 &&
|
||||
model->selected_keyboard == symbol_keyboard.keyboard_index) {
|
||||
if(model->selected_column > 7)
|
||||
model->selected_column -= 2;
|
||||
else if(model->selected_column > 1)
|
||||
model->selected_column -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wifi_text_input_handle_left(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
|
||||
UNUSED(wifi_text_input);
|
||||
if(model->selected_column > 0) {
|
||||
if(model->cursor_select) {
|
||||
if(model->cursor_pos > 0) {
|
||||
model->cursor_pos = CLAMP(model->cursor_pos - 1, strlen(model->text_buffer), 0u);
|
||||
}
|
||||
} else if(model->selected_column > 0) {
|
||||
model->selected_column--;
|
||||
} else {
|
||||
model->selected_column = get_row_size(model->selected_row) - 1;
|
||||
model->selected_column =
|
||||
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wifi_text_input_handle_right(WIFI_TextInput* wifi_text_input, WIFI_TextInputModel* model) {
|
||||
UNUSED(wifi_text_input);
|
||||
if(model->selected_column < get_row_size(model->selected_row) - 1) {
|
||||
if(model->cursor_select) {
|
||||
model->cursor_pos = CLAMP(model->cursor_pos + 1, strlen(model->text_buffer), 0u);
|
||||
} else if(
|
||||
model->selected_column <
|
||||
get_row_size(keyboards[model->selected_keyboard], model->selected_row) - 1) {
|
||||
model->selected_column++;
|
||||
} else {
|
||||
model->selected_column = 0;
|
||||
@@ -350,35 +446,49 @@ static void
|
||||
static void wifi_text_input_handle_ok(
|
||||
WIFI_TextInput* wifi_text_input,
|
||||
WIFI_TextInputModel* model,
|
||||
bool shift) {
|
||||
InputType type) {
|
||||
if(model->cursor_select) return;
|
||||
bool shift = type == InputTypeLong;
|
||||
bool repeat = type == InputTypeRepeat;
|
||||
char selected = get_selected_char(model);
|
||||
uint8_t text_length = strlen(model->text_buffer);
|
||||
|
||||
if(shift) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
size_t text_length = strlen(model->text_buffer);
|
||||
|
||||
if(selected == ENTER_KEY) {
|
||||
if(model->validator_callback &&
|
||||
(!model->validator_callback(
|
||||
model->text_buffer, model->validator_text, model->validator_callback_context))) {
|
||||
model->valadator_message_visible = true;
|
||||
model->validator_message_visible = true;
|
||||
furi_timer_start(wifi_text_input->timer, furi_kernel_get_tick_frequency() * 4);
|
||||
} else if(model->callback != 0 && text_length > 0) {
|
||||
} else if(model->callback != 0 && text_length >= model->minimum_length) {
|
||||
model->callback(model->callback_context);
|
||||
}
|
||||
} else if(selected == BACKSPACE_KEY) {
|
||||
wifi_text_input_backspace_cb(model);
|
||||
} else if(selected == SWITCH_KEYBOARD_KEY) {
|
||||
switch_keyboard(model);
|
||||
} else {
|
||||
if(model->clear_default_text) {
|
||||
text_length = 0;
|
||||
}
|
||||
if(text_length < (model->text_buffer_size - 1)) {
|
||||
model->text_buffer[text_length] = selected;
|
||||
model->text_buffer[text_length + 1] = 0;
|
||||
if(selected == BACKSPACE_KEY) {
|
||||
wifi_text_input_backspace_cb(model);
|
||||
} else if(!repeat) {
|
||||
if(model->clear_default_text) {
|
||||
text_length = 0;
|
||||
}
|
||||
if(text_length < (model->text_buffer_size - 1)) {
|
||||
if(shift != (text_length == 0)) {
|
||||
selected = char_to_uppercase(selected);
|
||||
}
|
||||
if(model->clear_default_text) {
|
||||
model->text_buffer[0] = selected;
|
||||
model->text_buffer[1] = '\0';
|
||||
model->cursor_pos = 1;
|
||||
} else {
|
||||
char* move = model->text_buffer + model->cursor_pos;
|
||||
memmove(move + 1, move, strlen(move) + 1);
|
||||
model->text_buffer[model->cursor_pos] = selected;
|
||||
model->cursor_pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
model->clear_default_text = false;
|
||||
}
|
||||
model->clear_default_text = false;
|
||||
}
|
||||
|
||||
static bool wifi_text_input_view_input_callback(InputEvent* event, void* context) {
|
||||
@@ -391,8 +501,8 @@ static bool wifi_text_input_view_input_callback(InputEvent* event, void* context
|
||||
WIFI_TextInputModel* model = view_get_model(wifi_text_input->view);
|
||||
|
||||
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
|
||||
model->valadator_message_visible) {
|
||||
model->valadator_message_visible = false;
|
||||
model->validator_message_visible) {
|
||||
model->validator_message_visible = false;
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
consumed = true;
|
||||
@@ -410,7 +520,7 @@ static bool wifi_text_input_view_input_callback(InputEvent* event, void* context
|
||||
wifi_text_input_handle_right(wifi_text_input, model);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
wifi_text_input_handle_ok(wifi_text_input, model, false);
|
||||
wifi_text_input_handle_ok(wifi_text_input, model, event->type);
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
@@ -432,7 +542,7 @@ static bool wifi_text_input_view_input_callback(InputEvent* event, void* context
|
||||
wifi_text_input_handle_right(wifi_text_input, model);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
wifi_text_input_handle_ok(wifi_text_input, model, true);
|
||||
wifi_text_input_handle_ok(wifi_text_input, model, event->type);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
wifi_text_input_backspace_cb(model);
|
||||
@@ -456,6 +566,9 @@ static bool wifi_text_input_view_input_callback(InputEvent* event, void* context
|
||||
case InputKeyRight:
|
||||
wifi_text_input_handle_right(wifi_text_input, model);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
wifi_text_input_handle_ok(wifi_text_input, model, event->type);
|
||||
break;
|
||||
case InputKeyBack:
|
||||
wifi_text_input_backspace_cb(model);
|
||||
break;
|
||||
@@ -478,7 +591,7 @@ void wifi_text_input_timer_callback(void* context) {
|
||||
with_view_model(
|
||||
wifi_text_input->view,
|
||||
WIFI_TextInputModel * model,
|
||||
{ model->valadator_message_visible = false; },
|
||||
{ model->validator_message_visible = false; },
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -496,7 +609,12 @@ WIFI_TextInput* wifi_text_input_alloc() {
|
||||
with_view_model(
|
||||
wifi_text_input->view,
|
||||
WIFI_TextInputModel * model,
|
||||
{ model->validator_text = furi_string_alloc(); },
|
||||
{
|
||||
model->validator_text = furi_string_alloc();
|
||||
model->minimum_length = 1;
|
||||
model->cursor_pos = 0;
|
||||
model->cursor_select = false;
|
||||
},
|
||||
false);
|
||||
|
||||
wifi_text_input_reset(wifi_text_input);
|
||||
@@ -528,11 +646,14 @@ void wifi_text_input_reset(WIFI_TextInput* wifi_text_input) {
|
||||
wifi_text_input->view,
|
||||
WIFI_TextInputModel * model,
|
||||
{
|
||||
model->text_buffer_size = 0;
|
||||
model->header = "";
|
||||
model->selected_row = 0;
|
||||
model->selected_column = 0;
|
||||
model->selected_keyboard = 0;
|
||||
model->minimum_length = 1;
|
||||
model->clear_default_text = false;
|
||||
model->cursor_pos = 0;
|
||||
model->cursor_select = false;
|
||||
model->text_buffer = NULL;
|
||||
model->text_buffer_size = 0;
|
||||
model->callback = NULL;
|
||||
@@ -540,7 +661,7 @@ void wifi_text_input_reset(WIFI_TextInput* wifi_text_input) {
|
||||
model->validator_callback = NULL;
|
||||
model->validator_callback_context = NULL;
|
||||
furi_string_reset(model->validator_text);
|
||||
model->valadator_message_visible = false;
|
||||
model->validator_message_visible = false;
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -566,15 +687,28 @@ void wifi_text_input_set_result_callback(
|
||||
model->text_buffer = text_buffer;
|
||||
model->text_buffer_size = text_buffer_size;
|
||||
model->clear_default_text = clear_default_text;
|
||||
model->cursor_select = false;
|
||||
if(text_buffer && text_buffer[0] != '\0') {
|
||||
model->cursor_pos = strlen(text_buffer);
|
||||
// Set focus on Save
|
||||
model->selected_row = 2;
|
||||
model->selected_column = 8;
|
||||
model->selected_column = 9;
|
||||
model->selected_keyboard = 0;
|
||||
} else {
|
||||
model->cursor_pos = 0;
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void wifi_text_input_set_minimum_length(WIFI_TextInput* wifi_text_input, size_t minimum_length) {
|
||||
with_view_model(
|
||||
wifi_text_input->view,
|
||||
WIFI_TextInputModel * model,
|
||||
{ model->minimum_length = minimum_length; },
|
||||
true);
|
||||
}
|
||||
|
||||
void wifi_text_input_set_validator(
|
||||
WIFI_TextInput* wifi_text_input,
|
||||
WIFI_TextInputValidatorCallback callback,
|
||||
|
||||
@@ -22,27 +22,27 @@ WIFI_TextInput* wifi_text_input_alloc();
|
||||
|
||||
/** Deinitialize and free text input
|
||||
*
|
||||
* @param wifi_text_input WIFI_TextInput instance
|
||||
* @param text_input WIFI_TextInput instance
|
||||
*/
|
||||
void wifi_text_input_free(WIFI_TextInput* wifi_text_input);
|
||||
void wifi_text_input_free(WIFI_TextInput* text_input);
|
||||
|
||||
/** Clean text input view Note: this function does not free memory
|
||||
*
|
||||
* @param wifi_text_input Text input instance
|
||||
* @param text_input Text input instance
|
||||
*/
|
||||
void wifi_text_input_reset(WIFI_TextInput* wifi_text_input);
|
||||
void wifi_text_input_reset(WIFI_TextInput* text_input);
|
||||
|
||||
/** Get text input view
|
||||
*
|
||||
* @param wifi_text_input WIFI_TextInput instance
|
||||
* @param text_input WIFI_TextInput instance
|
||||
*
|
||||
* @return View instance that can be used for embedding
|
||||
*/
|
||||
View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input);
|
||||
View* wifi_text_input_get_view(WIFI_TextInput* text_input);
|
||||
|
||||
/** Set text input result callback
|
||||
*
|
||||
* @param wifi_text_input WIFI_TextInput instance
|
||||
* @param text_input WIFI_TextInput instance
|
||||
* @param callback callback fn
|
||||
* @param callback_context callback context
|
||||
* @param text_buffer pointer to YOUR text buffer, that we going
|
||||
@@ -53,7 +53,7 @@ View* wifi_text_input_get_view(WIFI_TextInput* wifi_text_input);
|
||||
* event
|
||||
*/
|
||||
void wifi_text_input_set_result_callback(
|
||||
WIFI_TextInput* wifi_text_input,
|
||||
WIFI_TextInput* text_input,
|
||||
WIFI_TextInputCallback callback,
|
||||
void* callback_context,
|
||||
char* text_buffer,
|
||||
@@ -61,22 +61,23 @@ void wifi_text_input_set_result_callback(
|
||||
bool clear_default_text);
|
||||
|
||||
void wifi_text_input_set_validator(
|
||||
WIFI_TextInput* wifi_text_input,
|
||||
WIFI_TextInput* text_input,
|
||||
WIFI_TextInputValidatorCallback callback,
|
||||
void* callback_context);
|
||||
|
||||
WIFI_TextInputValidatorCallback
|
||||
wifi_text_input_get_validator_callback(WIFI_TextInput* wifi_text_input);
|
||||
void wifi_text_input_set_minimum_length(WIFI_TextInput* text_input, size_t minimum_length);
|
||||
|
||||
void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* wifi_text_input);
|
||||
WIFI_TextInputValidatorCallback wifi_text_input_get_validator_callback(WIFI_TextInput* text_input);
|
||||
|
||||
void* wifi_text_input_get_validator_callback_context(WIFI_TextInput* text_input);
|
||||
|
||||
/** Set text input header text
|
||||
*
|
||||
* @param wifi_text_input WIFI_TextInput instance
|
||||
* @param text_input WIFI_TextInput instance
|
||||
* @param text text to be shown
|
||||
*/
|
||||
void wifi_text_input_set_header_text(WIFI_TextInput* wifi_text_input, const char* text);
|
||||
void wifi_text_input_set_header_text(WIFI_TextInput* text_input, const char* text);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
338
applications/external/wifi_scanner/wifi_scanner.c
vendored
338
applications/external/wifi_scanner/wifi_scanner.c
vendored
@@ -11,8 +11,6 @@
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <u8g2.h>
|
||||
|
||||
#include "FlipperZeroWiFiModuleDefines.h"
|
||||
|
||||
#define WIFI_APP_DEBUG 0
|
||||
@@ -104,6 +102,238 @@ typedef struct SWiFiScannerApp {
|
||||
uint8_t m_animtaionCounter;
|
||||
} SWiFiScannerApp;
|
||||
|
||||
/*
|
||||
Fontname: -FreeType-Inconsolata LGC-Bold-R-Normal--36-360-72-72-P-176-ISO10646-1
|
||||
Copyright: Original Roman version created by Raph Levien using his own tools and FontForge. Copyright 2006 Raph Levien. Hellenisation of the Roman font, by Dimosthenis Kaponis, using FontForge. Hellenic glyphs Copyright 2010-2012 Dimosthenis Kaponis. Released under the SIL Open Font License, http://scripts.sil.org/OFL. Cyrillic glyphs added by MihailJP, using FontForge. Cyrillic glyphs Copyright 2012 MihailJP. Released under the SIL Open Font License, http://scripts.sil.org/OFL. Emboldened by MihailJP. Some glyphs modified by Greg Omelaenko, using FontForge.
|
||||
Glyphs: 95/658
|
||||
BBX Build Mode: 2
|
||||
*/
|
||||
const uint8_t u8g2_font_inb27_mr[4414] =
|
||||
"_\2\5\4\5\6\1\4\6\26%\0\370\33\371\35\371\5e\13\313\21! \13\266\14\366\207\377\377\377"
|
||||
"\20\0!\30\266\14\366\7`\310\22\353E\42\351\177r|(\220h\240-\222\17\37\42%\266\14v\37"
|
||||
"d,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203|\370\377\307\1#"
|
||||
"M\266\14\366\7u\220\261\310 \213\14\262\310 \213\14\262\310 k\20b\36 \343\1\62\36 \3;"
|
||||
"d\220E\6Yd\220\65\10Y\203\220\365\306\3c<@\306\3\344\220A\26\31d\221A\326 d\15"
|
||||
"\62\330 \203\15\62\26!\343\303\63\0$A\266\14\366\7\200H\352\251\325\320;$\220P\14\21d\210"
|
||||
"C\4\31\1\21AX\11\244e.\271\325\64F\202YD\224E\6Yd\20\23\10\31\244\214AD!"
|
||||
"&\220P\314Cm\251G$\365\341\42\0%I\266\14\366\7\261\34RN!%\21B\226 \205\14\42"
|
||||
"H!\203\4b\310H\346!\227N \253\204\22I,\221\222d\10F\302Q\15\221\220N\32\304\220@"
|
||||
"\6)%\220A\12\21d\20R\304\42\204$R\312)\344\224\17/\3&F\266\14\366\7\264\274\304\326"
|
||||
"b\251\214\222H!\211\24\222H!\212\14\262\310 \214\4\322\220;\16\65E\302!\202\220A\250A\221"
|
||||
"\22\310 &\15r\16!\250\224bL)\5\225\7Fa\241\224\64\310\61F|x\30\0'\17\266\14"
|
||||
"\366\7aH\372\357\303\377\177\1\0((\266\14v\14sD\363\216\63\317@\22\13,\221\304\22\211$"
|
||||
"\261D\42\351\223ER\262\304\42K,\262\212v\261L\241\1)$\266\14\266\26\263D\233\254\305\42K"
|
||||
",\222\310\42\351_$\222\304\22I,\260\304\2\313\263\301\22\307\7\7\0*/\266\14\366\207\207\210\244"
|
||||
"\261PH\11\205\14\62F\61a\10C\36\30\306\261\2\317C\215\10\262\310(\251\20\202\212!h\234\261"
|
||||
"\2\12\37\376,\0+\33\266\14\366\207\207\210\244\267\36\30\344\201A\36\30\344\201\261\210\244\337\207\277\14"
|
||||
"\0,\30\266\14\366\207\377\377\300\220%\32hI\42\307\34rH\42\7\15\15\0-\26\266\14\366\207\177"
|
||||
"\352\201`\36\10\346\201`\36\10\37\376\277\4\0.\21\266\14\366\207\377\377\0\211\6\332\42\371p\22\0"
|
||||
"/.\266\14\366\33\223\304\22I,\221H\22\211$\221H\22\211$\221H\22K$\261D\22K$\261"
|
||||
"D\42I$\222D\42\211\34\65|x\17\0\60I\266\14\366\7\266<\324\324b\251\220\202\210!\247\230"
|
||||
"b\310)\206\30SJA\204\24\22\10!e\10B\10\31\203\20\62(B\306 \224\30\205\20\22\206!"
|
||||
"\4\31R\214)\245\34b\312!\247\224r\12)\211-\325\20,\37^\7\61\26\266\14\366\7\226@\363"
|
||||
"NKL\265!\210\244\377\377\367\341y\0\62'\266\14\366\7\325\70\265Xr\247\24s\306)($\42"
|
||||
"i\261D\22\13\254\277H\311g\36\10\346\201`\36\10\37\36\6\63-\266\14\366\7\324\70\265Xri"
|
||||
"\230\222\2\42\222\26\313\63,\265\363RS\261\310\42i) \202\304)\207\224r\36jj\265\363\341y"
|
||||
"\0\64\65\266\14\366\7\232H\22\13\264\336q\310\215@\32\11\204\21A\330\30d\221A\24!$\221B"
|
||||
"\22)\4\21C\316\3\203<\60\310\3\203<\60\36\221\364}x\32\0\65*\266\14\366\7\361\235\337!"
|
||||
"\222N\20\306TK\16\25b\316\70%\5T$\275#P)\4\21cJ\61\17\265\245\234\371\360:\0"
|
||||
"\66>\266\14\366\7\327\70\265Xj\250\224\221\310\11\211H\22K$\243(\22\22z\347\201`L)\246"
|
||||
"\234R\10*\205$RH\42\205$R\12\42\206\234b\212!\250\220\202\232b+=\363\341q\0\67-"
|
||||
"\266\14\366\7\360\201`\36\10\346\201`\236$\261D\22K$\222\304\22I,\221H\22K$\222\304\22"
|
||||
"I\254\42\211U$\261|\370\4\0\70;\266\14\366\7\325\70\265Xj\250\224r\212!\207\356\24C\20"
|
||||
")$\225Q\324b\251)U\204I\244\224C\31\202J!\211\24\222H!\211\224r\212)\245\234\207\232"
|
||||
"Z\355|x\35\0\71\71\266\14\366\7\265\274\304\326b\251\220\202\210!\247\230b\10\42\206 b\10\42"
|
||||
"\206 b\312\241L\71\205\30\344\251\23\10\33\203H\42\207$*\34\222D)\251%\266\322+\37>:"
|
||||
"\27\266\14\366\207\77A\242\201\266H>|\210D\3m\221|\70\11\0;\34\266\14\366\207\77A\242\201"
|
||||
"\266H>|\210D\3\255X$\221C\222HM\361\1\1< \266\14\366\207\271\60G,\357\264\304\360"
|
||||
"\265\363J<\20\301\23/\210\301\3\215$T|\370\25\0= \266\14\366\207\317=\60\310\3\203<\60"
|
||||
"\310\3\343\303\352\3\203<\60\310\3\203<\60>\374g\1>\36\266\14\366\207\266\240D\32\210\37<\261"
|
||||
"\274\323\20\303\332\325P;\257\304\61\305\207\277\6\0\77%\266\14\266\67N\251\206\236\61\245\34r\312\21"
|
||||
"\211H*\226Hb\201u\221H\352C\226D\3m\221|x\36\0@G\266\14\366\7\266\274\264\32r"
|
||||
"\247\230b\10\42\205(B\306Ad\24\65\6ac\20\66\306(\204\214\61H!c\14R\310\30\203\24"
|
||||
"\62\306\250\306\30m\220\301\310 \213\20R\2!d\222YNH.\265\245\234\371\360\70\0A<\266\14"
|
||||
"\366\7\67PA\307\34\262\304\2\15<\357\70\22H#\201\264!\10#\203,\62\310\32e(RHj"
|
||||
"\311\235\357\220S\12I\244\220T\6Yd\220E\6Y%\220F><\13\0BD\266\14\366\7\217)"
|
||||
"\207\36\10\346\201`\310\61\205\240RH\42\205$RH\42\205\240R\310)\346\201`\336\371@\60\4\225"
|
||||
"BR!D\21B\24!D\21B\24!$\25B\220!\17\210\362@\60\357\264\17\217\3C/\266\14"
|
||||
"\366\7\327\264\245\32z\306\24S\312)\244$B\210\22\206\304\22\211\244'K,\222\310\22\213\12\247\240"
|
||||
"a\214)\346\241\246V\63\37\36\7DC\266\14\366\7o\255\226\336y\207\30c\10*\205\240RH\42"
|
||||
"\205\244B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204\244BH\42\205\240"
|
||||
"R\10\42\206\30c\336q\250\245\365\341y\0E'\266\14\366\7\357\1Q\36\20\345\1Q\36\20\205H"
|
||||
"\372\344;\277C$\375\344\3\242< \312\3\242< ><\14\0F\35\266\14\366\7\360\201`\36\10"
|
||||
"\346\201`\36\10\206H\372\244C>D$\375\357\303W\0G:\266\14\366\7\326\70\245\32z\306\24S"
|
||||
"\312)\244$a\210$\261D\42i&\15b\322 &\15b\322(\212\20\242\10!\212\220\222H)\210"
|
||||
"\24c\212y \34\227\30;\37\36\7HM\266\14\366\7\217$RH\42\205$RH\42\205$RH"
|
||||
"\42\205$RH\42\205$RH\42\205$R\36\20\345\1Q\36\20\345\1QH\42\205$RH\42\205"
|
||||
"$RH\42\205$RH\42\205$RH\42\205$RH\42\205$\362\341a\0I\24\266\14\366\7\320"
|
||||
"!_#\222\376\377k\357\374>\274\14\0J\33\266\14\366\7\264\245\236#\222\376\377\222\60%\215BR"
|
||||
"S\213\245W>|\1\0KI\266\14\366\7\257\244\62H*\204\240R\310)\206\230rH)\210\24\222"
|
||||
"\10!\212\14\262\210(\213\204\302RKM\261\22\312\42\203,\62\212\42\244$RH\42\245 b\312!"
|
||||
"\247\30r\212!\250\24\222\12!\251\20\242\312\207g\1L\32\266\14\366\7\260D\42\351\377\377\311\7D"
|
||||
"y@\224\7Dy@|x\27\0MU\266\14\366\7\217,\62\310\42\243\244\62J*\303\34\63\314\61"
|
||||
"\343\224\63N\71\3\33$\214\61\2\31$\320\6\21#\14A\6\21#\14A\6\31eP\243\14\32!"
|
||||
"\203\220A\310 \213\14\262\310 \213\14\262\310 \213\14\262\310 \213\14\262\310 \213\14\262\310\207g\1"
|
||||
"NS\266\14\366\7\217(BJ\42\244$B\14\42\304 B\316!\344\34B\220!\204\4R\10!\201"
|
||||
"\24B\210 \204\22\204P\203\42dP\204\22\204P\202\20RH \204\230\21\10!\6\21r\16!\347"
|
||||
"\20\202\14!\310\20\222\12!\251\20\242\10!\212|x\27\0OC\266\14\366\7\325\70\265Xr\247\224"
|
||||
"r\310)\245 RH*\204(\62\212\42\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\212"
|
||||
"\42\204(BH*\244 b\310)\246\224\202\134bK\71\363\341u\0P\60\266\14\366\7\257\245w\36"
|
||||
"\10\346\1Q\10*\205\244B\210\42\204(B\210\42\204(BH*\204\240R\36\20\345\201`\34b\212"
|
||||
"H\372\357\303g\0QJ\266\14\366\7\325\70\265Xr\247\224r\310)\245 RH*\204\244\62\212\42"
|
||||
"\203,\62\310\42\203,\62\310\42\203,\62\310\42\203,\62\212\42\204\244BH*\244 b\310)\246\224"
|
||||
"\202\134b+\271\23\211$R\265\344\20\64\37@\0RC\266\14\366\7\217)\207\336y \30rL!"
|
||||
"\250\24\222H!\211\24\222H!\211\24\202J!\247\230\7\202y\307!\246H!\211\24\222H)\210\30"
|
||||
"\202\210)\207v\212!\210\30\202J!\211\24\222\312\207w\1S\61\266\14\366\7\365\264\245\32z\207\230"
|
||||
"\12\211C\222\70DV\321D\364\262\207\242\221ER&,b\302\42e\244B\214)\345\1a^b\354"
|
||||
"|x\35\0T\27\266\14\366\7\356\1\62\36 \343\1\62\36 \212H\372\377\377>|UH\266\14\366"
|
||||
"\7\257$B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\204"
|
||||
"(B\210\42\204(B\210\42\204(B\210\42\204(B\210\42\244\240B\12*\245\230b\36rJ\71\363"
|
||||
"\341u\0V>\266\14\366\7\216\60\42\10#\203(B\210\42\204(R\10\42\206 b\10\42\207\30\202"
|
||||
"\210!\210\30\222H\31\212\20\242\10!\213\214\301\210 \214\10\322H\30\16{\6Z\221H\42\7\25\37"
|
||||
">W\134\266\14\366\7n\22\303\15A\212(D\220\62\10\21\244\14B\4!\204\214A\10!\23)c"
|
||||
"\20\62\312\30\204\10\63\6!\302\10B\210\70\201\20\42N\30f\204!F\30\346\210\21\206\71\342\230#"
|
||||
"\216\61\304\30C\12*\244\240B\12\42\206 b\10\42\206\240q\206\22H(\201\304\207\247\1XB\266"
|
||||
"\14\366\7\217(BH\42\206 b\212!\210\224\202\12!\212\214\242\212 \214\204\302\222;\320\300\22K"
|
||||
"\64\357<\324\24#\202,\62\212\42\204$R\12\42\206\34rJ)\210\24\222\312(\252|x\26\0Y"
|
||||
"\60\266\14\366\7\216\254\42\212\42\204\244B\12\42\206 b\212!\210\30\202\12!\212\20\242\212 \214\10"
|
||||
"\322H\30\16\275\363L,\221H\372\357\303\363\0Z\63\266\14\366\7\360\1Q\36\20\345\1Q\36\10\222"
|
||||
"D\22K\244b\211$\226H\305\22I,\260D\22\13,\261\300\22\37\20\344\201A\36\30\344\201\361\341"
|
||||
"]\0[\23\266\14\366n\251\227\210\244\377\377\77\331R\357C\10\0\134+\266\14\66\21\262H\42\213$"
|
||||
"\262H\42\213$\262Hj\22I&\221d\22Id\221D\26Id\221D\26IM\42\311\14\37\36\1"
|
||||
"]\20\266\14vn\251'\351\377\377_\352\373\220\2^!\266\14\366\7WL\42I\64\357<\324\210 "
|
||||
"\213\14\262\10!\211\24\222\210!I\34\361\341\377\17\2_\26\266\14\366\207\377\377\247\36 \343\1\62\36"
|
||||
" \343\1\362!\3\0`\33\266\14\266\11UPA\307$\222\310\22\213,\261\310\42\251\71Q\361\341\377"
|
||||
"g\0a\60\266\14\366\207\217\236\266\222C.\15S$\325Rj\347\231\7\202)\207\224\202H!\211\24"
|
||||
"\202J)\345\230\7\202y \34\25H\62\203|x\30\0b;\266\14\66.\221H\372\215\242HH\350"
|
||||
"\235\7\202\61\305\224rJ!\251\20\222\12!\212\20\242\10!\212\20\242\10!\212\20\222\12)\210\24c"
|
||||
"Jy \230w\206Hh\220\362\341u\0c(\266\14\366\207\257\32\247\224;\17\4S\225\202\206!I"
|
||||
"\230\22\211\244\311\42\211,H\240b\310y \34\247\224\63\37\36\7d;\266\14\366\7\207H\372\251\62"
|
||||
"\10J\201\234g\36\10\245\30S\10*\244\240BH*\204(B\210\42\204(B\210\42\244\240B\12*"
|
||||
"\245\234R,\363@\70\17\245@T\31\344\303\273\0e,\266\14\366\207\217\236\266TC\317T\206 b"
|
||||
"H\42\344\201A\36\30\344\201A\36\30\204H\42\253\24\216\61\344<\344\322r\346\303\343\0f\35\266\14"
|
||||
"\366\7\302\70\265Xj\250\230\201\312\11\211H\312\71\344cD\322\377\367\341\23\0g=\266\14\366\207o"
|
||||
"\26R\314\3\241< \10!j\224R\16}\247\224r\314(\251\251\265\324\42a\64\42[z \234\7"
|
||||
"\202y@\20\222\312 \213\14\262\310(\251\214\7Fy \34\267\220\7h<\266\14v.\221H\372\215"
|
||||
"\242\210@\210\4u\336\71\244\30c\210)\207\30\202\210!\210\30\202\210!\210\30\202\210!\210\30\202\210"
|
||||
"!\210\30\202\210!\210\30\202\210!\210\30\202\310\207\207\1i\30\266\14\366\7`\310\22+\71>$S"
|
||||
"\313I\372\277\326R\357\303\323\0j\37\266\14\366\7d\310\22+\71>\364\230\342I\372\377\227\204)\210"
|
||||
"\220\202\134bK\71\363A\0k\71\266\14v.\221H\372\241R\310)\206\230rH)\210\220\222\310("
|
||||
"\212\210\262H(Lck\25Q\24!%\221R\20)\5\21S\16\71\305\20T\12A\206\220d>\274"
|
||||
"\12\0l\21\266\14vVL'\351\377\377\330;\277\17/\3m@\266\14\366\207\257\221PF!+\234"
|
||||
"\361\0\31\17\24QF\21\325 \204\10B(A\10%\10\241\4!\224 \204\22\204P\202\20J\20B"
|
||||
"\11B(A\10%\10\241\4!\224 \204\22\204P\37\236\5n:\266\14\366\207\357\221Q\24\21\10\275"
|
||||
"\363\316!\305\224CL\71\304\20D\14A\304\20D\14A\304\20D\14A\304\20D\14A\304\20D\14"
|
||||
"A\304\20D\14A\304\20D><\14\0o\62\266\14\366\207\257\32\247TC\357\224bJ\71\245\220T"
|
||||
"FIe\220E\6Yd\220E\6Yd\24E\10I\244\224SL)\306<\324\324r\346\303\343\0p"
|
||||
"=\266\14\366\207\317\221Q\24\11\11=\20\314\3\301\230bJ\71\245\220T\10I\205\20E\10Q\204\20"
|
||||
"E\10Q\204\20E\10I\205\24D\212\61\245<\20\314;$$DFQD\322\367\301\1q\71\266\14"
|
||||
"\366\207\217\32AP\12\344<\363@(\305\230BP!\5\25B\24!D\21B\24!D\21B\24!"
|
||||
"%\221BP)\345\224b\231\7\302y(\5\242\312 \222~\30\0r\37\266\14\366\207\17\22R\22\21"
|
||||
"\351<\20\314\3\301\34#\216\71\342\224X\42\221\364\277\17\37\1s,\266\14\366\207\217\232\306\222C\317"
|
||||
"\24C\16A\343\24\24R\211\351)\227\340\221\305\10E\214P\244\224S\312\3\341\270\304\332\371\360:\0"
|
||||
"t\35\266\14\366\207\234\220\364\332;\277E$\375\223\305\4U\212XL\261\245\232\371\360\66\0u;\266"
|
||||
"\14\366\207\317\221D\12I\244\220D\12I\244\220D\12I\244\220D\12I\244\220D\12I\244\220D\12"
|
||||
"I\244\220DJ\71\245\224SL)\306<\20\316C)\20U\6\371\360\60\0v\63\266\14\366\207\257\25"
|
||||
"E\10Q\204\20E\12I\303\20DL\71\3\21C\20\61$\221\62\24!D\21\62\30\21\204\21A\32"
|
||||
"\11\303!w\240\201E\22\71>|wH\266\14\366\207\217Q\202\60\42H\31\204\214Q\6!c\224A"
|
||||
"\310 \243\14j\224A\215\62F\31\303\210Q\206\30a\210QH\230\304($Lb\24\22\204@\306\14"
|
||||
"s\314\60\307\14sJ)\247\224\202H!\211\24\362\341i\0x\63\266\14\366\207\317\221DJ\71\305\24"
|
||||
"C\20)D\221QT\21\204%\207\334\201%\232w\36j$\224U\4Q\205\220DJ\71\305\224R\20"
|
||||
")$\225\17\357\2y<\266\14\366\207\317\225T\10I\244\220DJA\304\220CC\304\20D\12I\205"
|
||||
"\20E\310Xd\20F\4aD\14\67\2q\347\35h`\221T$,\24\262\4!L-\325\320+\37"
|
||||
"\24\0z&\266\14\366\207\357=\20\314\3\301<\20\314\213$\26X\213$\26X\27\13|@\220\7\6"
|
||||
"y`\220\7\306\207w\1{$\266\14\366\7\342\264\304\324Z\253\300\22\211\244_$\357<\3\15<\262"
|
||||
"H\372'K,r\255\305\224C\32\0|\16\266\14\366\7\200H\372\377\377\377\357\3}#\266\14\266\66"
|
||||
"\20\271\324\224,\222\376d\221d\36h\336q\310\221H$\375\213e)\246Xj\347\3\1\0~\31\266"
|
||||
"\14\366\207/\232\23\214\42d<\60\306\3\303\210\202`\371\360\377\303\0\0\0\0\4\377\377\0";
|
||||
|
||||
/*
|
||||
Fontname: open_iconic_arrow_2x
|
||||
Copyright: https://github.com/iconic/open-iconic, SIL OPEN FONT LICENSE
|
||||
Glyphs: 28/28
|
||||
BBX Build Mode: 0
|
||||
*/
|
||||
const uint8_t u8g2_font_open_iconic_arrow_2x_t[644] =
|
||||
"\34\0\4\4\5\5\4\4\6\20\20\0\0\16\0\16\0\0\17\0\0\2g@\17\352i\302$P\376\221"
|
||||
"\12\64\246\310\11\2A\22O%\303\24Z\360X\242\17^\20\36-<(\0B\22O!\303\32\134\364"
|
||||
"`\22\17\236\222\35,:\20\0C\17\352)\302$\216\224\31\24\212\4\312\77\2D\37\20\42\302eP"
|
||||
"\25!\62\205\212\24*a\210#\304E\17\222 F\244P\231\42\245\24\232\2E \20\42\302ePU"
|
||||
"\11\63E\216\220\71Ah-a\302e\15\241 s\244\310\231\22\246\24\232\2F\37\20\42\302eP\225"
|
||||
"\211\62G\212\234!\201\310laj\27\221\70C\344H\31\23\245\24\232\2G\37\20\42\302ePU\221"
|
||||
"\62\205\212\20#A\360haD\34\231(T\244P\31B\244\24\232\2H\21\12.\302C\214\376\215\212"
|
||||
"$\207\212\15\14\4\0I\23P\341\302\25\134\364`\27\17\36\204xBz\270P\0J\23P\341\302*"
|
||||
"|\64\221\27\17\36\204p<Zx(\0K\21\12.\302\24pX\241#)\324\20\243\177\3\0L\16"
|
||||
"\356d\303\340\202\215*t&\311\12\3M\24\307u\302\26J\320\30\42%\36\224\60R\206\320(a\1"
|
||||
"N\25\307q\302\20L\324 \62EL<(Q\204\314 Q\301\0O\15\356$\303&\226\244\71Tj"
|
||||
"X\70P\24.%\303!P\4\261D%\212\224Q\205\316$Ya\0Q\20\311m\302&\214P\231:"
|
||||
"*UW\304D\0R\17\311m\302!\214T=*SG\304\204\1S\24.%\303&\226\244\71Tj"
|
||||
"\212\224(\224\214\204@\21\0T\23\20\42\302F\230^\252Ci\226\264x\230>x \0U\23\20\42"
|
||||
"\302\360\201x\230\212&k\22\235J\302\364\14\0V\34\320\241\302\34\36\200\30\27/\204\12\21\32\36\302"
|
||||
"\240B\204\212x\341F<\200\300\0W\32\220\241\302&\230\354hq\202\304\221\21\306L\14\71A\342D"
|
||||
"\217%,\14\0X\37\20\42\302\302\210\221@A\2\205K$\314\210\70\42\344\204\30\23$\134BA\2"
|
||||
"\5q\2\0Y$\17\42\302\34\134\304\270TF\306\214\20\64bH\260\262\203\211\226\34\42$\320\230\21"
|
||||
"\42H\245+,:\10\0Z\30\220!\303\32\36\200\360\321\4S\61\351\206\324 q\202\4\206\12\17\0"
|
||||
"[\34\320\241\302`\324X\30q&D-J!&\211\230`a\204\313P\220@A\34\1\0\0\0\4"
|
||||
"\377\377\0";
|
||||
|
||||
/*
|
||||
Fontname: -Adobe-Courier-Bold-R-Normal--11-80-100-100-M-60-ISO10646-1
|
||||
Copyright: Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
|
||||
Glyphs: 18/873
|
||||
BBX Build Mode: 0
|
||||
*/
|
||||
const uint8_t u8g2_font_courB08_tn[199] =
|
||||
"\22\0\3\3\3\4\2\3\4\6\11\0\376\6\376\7\377\0\0\0\0\0\252 \5\0\353\0*\11$\357"
|
||||
"\212P$\241\0+\12-\353\12\206J\301\20\0,\7\233\345\221$\1-\5\15\357(.\5\212\351\20"
|
||||
"/\14\304\347K\212\205b\241X\14\0\60\12=\351\231Hx\221L\0\61\10>\351\22\21u\62\62\11"
|
||||
"=\351\231\250\211\264\34\63\14=\351\231\250I\206\24\311\4\0\64\14>\351\223\215\42ZlB\11\0\65"
|
||||
"\12=\351\270Q\324F\26\0\66\14=\351\231Hh\24\11E\62\1\67\13=\351\270\310D\62\221L\4"
|
||||
"\70\15=\351\231H(\222\211\204\42\231\0\71\14=\351\231H(\22\32E\62\1:\6\242\351\20\12\0"
|
||||
"\0\0\4\377\377\0";
|
||||
|
||||
/*
|
||||
Fontname: -Misc-Fixed-Bold-R-Normal--13-120-75-75-C-70-ISO10646-1
|
||||
Copyright: Public domain font. Share and enjoy.
|
||||
Glyphs: 95/1003
|
||||
BBX Build Mode: 0
|
||||
*/
|
||||
const uint8_t u8g2_font_7x13B_tr[1083] =
|
||||
"_\0\3\3\3\4\3\5\4\6\15\0\376\11\376\11\0\1}\2\330\4\36 \5\0\356\7!\7J\303"
|
||||
"\307\241D\42\10\235\332\207\204E\0#\20\315\302OR$r\230\244\34&I\221\10\0$\17N\302\227"
|
||||
"\214\22\321F\223\250Dh\42\0%\17N\302\307H\22\251\4e\212\221JD\64&\17N\302\317H\242"
|
||||
"\247\221$\62\251\210&\1'\7\42\327\307!\0(\14\314\302\227D$\21\251\211d\2)\15\314\302\207"
|
||||
"L$\23\251\210$\42\0*\15\66\306O(&:\224d\241\10\0+\13\66\306\227Pt(\11E\0"
|
||||
",\10\244\276\317\212\22\0-\6\16\316\207\1.\10\234\276\217\204\42\1/\14N\302\247\232P\246(\23"
|
||||
"\12\1\60\16N\302\227,\24\21\361$\11\305D\0\61\13N\302\227l\24\21\352\311\0\62\16N\302\17"
|
||||
"ED\22\212F\62\241\320\0\63\15N\302\207Q\246F\25\222$\24\0\64\15N\302\247lD\221\220H"
|
||||
"\207\240\2\65\16N\302\307!(\254\210\204B\222\204\2\66\16N\302\17ED\24VDL\22\12\0\67"
|
||||
"\15N\302\207QM(\23\312\204\62\0\70\16N\302\17E\304$\241\210\230$\24\0\71\16N\302\17E"
|
||||
"\304$)\12I\22\12\0:\14\304\276\217\204\42\207I(\22\0;\13\304\276\217\204\42\236L\224\0<"
|
||||
"\10N\302\247LW\35=\7&\312\207\35j>\11N\302\207T\67\35\1\77\16N\302\17ED\22\212"
|
||||
"fr\230P\4@\17N\302\17%\266R\211L\252\61\11\5\0A\13N\302\17E\304t\30q\22B"
|
||||
"\14N\302GE\304t\21\61]\0C\13N\302\17ED\324\223\204\2D\12N\302GE\304O\27\0"
|
||||
"E\13N\302\307!\250X\21*\32F\13N\302\307!\250X\21j\4G\14N\302\17EDT)\61"
|
||||
"I\12H\13N\302\207\210\323a\304I\0I\11N\302\207I\250O\6J\12N\302\247>\222$\24\0"
|
||||
"K\17N\302\207lD\221\220f$\211\22-\0L\10N\302\207P\77\32M\13N\302Gpt\70\210"
|
||||
"x\22N\15N\302\207\210T\251\34&M$\1O\13N\302\17E\304O\22\12\0P\13N\302GE"
|
||||
"\304t\21j\4Q\14V\276\17E\304S\205\62\241\12R\15N\302GE\304t!I\224h\1S\16"
|
||||
"N\302\17ED\224R\205$\11\5\0T\11N\302\207I\250\237\0U\12N\302\207\210\77I(\0V"
|
||||
"\15N\302\207\210I\22\312D\23*\1W\13N\302\207\210\247\303A\64\14X\17N\302Gp$\11\205"
|
||||
"h\62R\212h\30Y\14N\302\207\210$!\321\204:\1Z\12N\302\207QMG\241\1[\10\314\302"
|
||||
"\207I\237\10\134\14N\302\207P*\224*J\205\2]\10\314\302\7I\237\14^\11&\326\227\214\42\32"
|
||||
"\6_\7\26\276\307\241\0`\7\234\336\207L\1a\12\66\302\17Ur\42I\12b\13N\302\207P\261"
|
||||
"\42\342t\1c\13\66\302\17EDT\222P\0d\12N\302\247\226\23'I\1e\14\66\302\17Et"
|
||||
"\30\212$\24\0f\14N\302\327H\242(\243\11\265\1g\16F\272\317\22IB\221RD\22\12\0h"
|
||||
"\13N\302\207P\261\42\342I\0i\12N\302\227P\16\32\352dj\14^\272\247:L\250#IB\1"
|
||||
"k\15N\302\207P\23EB\42I\224\4l\10N\302\317P\77\31m\12\66\302\207Dr\70\61\11n"
|
||||
"\11\66\302GE\304\223\0o\12\66\302\17E\304IB\1p\13F\272GE\304t\21*\2q\12F"
|
||||
"\272\317\211IR\324\0r\11\66\302GED\324\10s\15\66\302\17E$\21KD\22\12\0t\14F"
|
||||
"\302\217PV\22j\21M\0u\11\66\302\207\210'I\1v\13\66\302\207\210IB\242\211\0w\13\66"
|
||||
"\302\207\210\351p\11E\0x\14\66\302\207\210$!QD$\1y\14F\272\207\210\223\244H\222P\0"
|
||||
"z\12\66\302\207Q&\222\11\15{\14\314\302OI&\221ID\262\1|\7J\303\307\3\1}\15\314"
|
||||
"\302\307L$\221Id\242\12\0~\11\36\332\217\350\20\222\0\0\0\0\4\377\377\0";
|
||||
|
||||
/////// INIT STATE ///////
|
||||
static void wifi_scanner_app_init(SWiFiScannerApp* const app) {
|
||||
app->m_context = Undefined;
|
||||
@@ -153,8 +383,8 @@ int16_t dBmtoPercentage(int16_t dBm) {
|
||||
void DrawSignalStrengthBar(Canvas* canvas, int rssi, int x, int y, int width, int height) {
|
||||
int16_t percents = dBmtoPercentage(rssi);
|
||||
|
||||
u8g2_DrawHLine(&canvas->fb, x, y, width);
|
||||
u8g2_DrawHLine(&canvas->fb, x, y + height, width);
|
||||
//u8g2_DrawHLine(&canvas->fb, x, y, width);
|
||||
//u8g2_DrawHLine(&canvas->fb, x, y + height, width);
|
||||
|
||||
if(rssi != NA && height > 0) {
|
||||
uint8_t barHeight = floor((height / 100.f) * percents);
|
||||
@@ -177,10 +407,8 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
const char* strError = "Something wrong";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strError) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) /
|
||||
2) /* - (u8g2_GetMaxCharHeight(&canvas->fb) / 2)*/,
|
||||
(128 / 2) - (canvas_string_width(canvas, strError) / 2),
|
||||
(64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
|
||||
strError);
|
||||
} break;
|
||||
case WaitingForModule:
|
||||
@@ -192,10 +420,8 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
const char* strConnectModule = "Attach WiFi scanner module";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strConnectModule) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) /
|
||||
2) /* - (u8g2_GetMaxCharHeight(&canvas->fb) / 2)*/,
|
||||
(128 / 2) - (canvas_string_width(canvas, strConnectModule) / 2),
|
||||
(64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
|
||||
strConnectModule);
|
||||
}
|
||||
#endif
|
||||
@@ -208,26 +434,19 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
const char* strInitializing = "Initializing...";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
(u8g2_GetDisplayWidth(&canvas->fb) / 2) -
|
||||
(canvas_string_width(canvas, strInitializing) / 2),
|
||||
(u8g2_GetDisplayHeight(&canvas->fb) / 2) -
|
||||
(u8g2_GetMaxCharHeight(&canvas->fb) / 2),
|
||||
(128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
|
||||
(64 / 2) - (canvas_current_font_height(canvas) / 2),
|
||||
strInitializing);
|
||||
}
|
||||
} break;
|
||||
case ScanMode: {
|
||||
uint8_t offsetY = 0;
|
||||
uint8_t offsetX = 0;
|
||||
canvas_draw_frame(
|
||||
canvas,
|
||||
0,
|
||||
0,
|
||||
u8g2_GetDisplayWidth(&canvas->fb),
|
||||
u8g2_GetDisplayHeight(&canvas->fb));
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
//canvas_set_font(canvas, FontPrimary);
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_7x13B_tr);
|
||||
uint8_t fontHeight = u8g2_GetMaxCharHeight(&canvas->fb);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr);
|
||||
uint8_t fontHeight = canvas_current_font_height(canvas);
|
||||
|
||||
offsetX += 5;
|
||||
offsetY += fontHeight;
|
||||
@@ -248,8 +467,8 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
furi_string_get_cstr(app->m_currentAccesspointDescription.m_bssid));
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
//u8g2_SetFont(&canvas->fb, u8g2_font_tinytim_tf);
|
||||
fontHeight = u8g2_GetMaxCharHeight(&canvas->fb);
|
||||
//canvas_set_custom_u8g2_font(canvas, u8g2_font_tinytim_tf);
|
||||
fontHeight = canvas_current_font_height(canvas);
|
||||
|
||||
offsetY += fontHeight + 1;
|
||||
|
||||
@@ -276,24 +495,20 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
offsetY += fontHeight;
|
||||
offsetY -= fontHeight;
|
||||
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_courB08_tn);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_courB08_tn);
|
||||
snprintf(
|
||||
string,
|
||||
sizeof(string),
|
||||
"%d/%d",
|
||||
app->m_currentIndexAccessPoint,
|
||||
app->m_totalAccessPoints);
|
||||
offsetX = u8g2_GetDisplayWidth(&canvas->fb) - canvas_string_width(canvas, string) - 5;
|
||||
offsetX = 128 - canvas_string_width(canvas, string) - 5;
|
||||
canvas_draw_str(canvas, offsetX, offsetY, string);
|
||||
|
||||
canvas_draw_frame(
|
||||
canvas,
|
||||
offsetX - 6,
|
||||
offsetY - u8g2_GetMaxCharHeight(&canvas->fb) - 3,
|
||||
u8g2_GetDisplayWidth(&canvas->fb),
|
||||
u8g2_GetDisplayHeight(&canvas->fb));
|
||||
canvas, offsetX - 6, offsetY - canvas_current_font_height(canvas) - 3, 128, 64);
|
||||
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_open_iconic_arrow_2x_t);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_open_iconic_arrow_2x_t);
|
||||
if(app->m_currentIndexAccessPoint != app->m_totalAccessPoints) {
|
||||
//canvas_draw_triangle(canvas, offsetX - 5 - 20, offsetY + 5, 4, 4, CanvasDirectionBottomToTop);
|
||||
canvas_draw_str(canvas, offsetX - 0 - 35, offsetY + 5, "\x4C");
|
||||
@@ -308,25 +523,21 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
uint8_t offsetY = 0;
|
||||
uint8_t offsetX = 0;
|
||||
|
||||
canvas_draw_frame(
|
||||
canvas,
|
||||
0,
|
||||
0,
|
||||
u8g2_GetDisplayWidth(&canvas->fb),
|
||||
u8g2_GetDisplayHeight(&canvas->fb));
|
||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||
|
||||
//canvas_set_font(canvas, FontBigNumbers);
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_inb27_mr);
|
||||
uint8_t fontHeight = u8g2_GetMaxCharHeight(&canvas->fb);
|
||||
uint8_t fontWidth = u8g2_GetMaxCharWidth(&canvas->fb);
|
||||
//canvas_set_custom_u8g2_font(canvas, u8g2_font_inb27_mr);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_inb27_mr);
|
||||
uint8_t fontHeight = canvas_current_font_height(canvas);
|
||||
uint8_t fontWidth = canvas_current_font_width(canvas);
|
||||
|
||||
if(app->m_currentAccesspointDescription.m_rssi == NA) {
|
||||
offsetX += floor(u8g2_GetDisplayWidth(&canvas->fb) / 2) - fontWidth - 10;
|
||||
offsetX += floor(128 / 2) - fontWidth - 10;
|
||||
offsetY += fontHeight - 5;
|
||||
|
||||
canvas_draw_str(canvas, offsetX, offsetY, "N/A");
|
||||
} else {
|
||||
offsetX += floor(u8g2_GetDisplayWidth(&canvas->fb) / 2) - 2 * fontWidth;
|
||||
offsetX += floor(128 / 2) - 2 * fontWidth;
|
||||
offsetY += fontHeight - 5;
|
||||
|
||||
char rssi[8];
|
||||
@@ -335,12 +546,12 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
}
|
||||
|
||||
//canvas_set_font(canvas, FontPrimary);
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_7x13B_tr);
|
||||
fontHeight = u8g2_GetMaxCharHeight(&canvas->fb);
|
||||
fontWidth = u8g2_GetMaxCharWidth(&canvas->fb);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr);
|
||||
fontHeight = canvas_current_font_height(canvas);
|
||||
fontWidth = canvas_current_font_width(canvas);
|
||||
|
||||
offsetX = 5;
|
||||
offsetY = u8g2_GetDisplayHeight(&canvas->fb) - 7 - fontHeight;
|
||||
offsetY = 64 - 7 - fontHeight;
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
offsetX,
|
||||
@@ -358,12 +569,7 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
DrawSignalStrengthBar(
|
||||
canvas, app->m_currentAccesspointDescription.m_rssi, 5, 5, 12, 25);
|
||||
DrawSignalStrengthBar(
|
||||
canvas,
|
||||
app->m_currentAccesspointDescription.m_rssi,
|
||||
u8g2_GetDisplayWidth(&canvas->fb) - 5 - 12,
|
||||
5,
|
||||
12,
|
||||
25);
|
||||
canvas, app->m_currentAccesspointDescription.m_rssi, 128 - 5 - 12, 5, 12, 25);
|
||||
} break;
|
||||
case ScanAnimation: {
|
||||
uint32_t currentTime = furi_get_tick();
|
||||
@@ -380,18 +586,15 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_draw_disc(
|
||||
canvas,
|
||||
offsetX + 30 + 25 * i,
|
||||
u8g2_GetDisplayHeight(&canvas->fb) / 2 - 7,
|
||||
64 / 2 - 7,
|
||||
5 * (app->m_animtaionCounter == i ? mutliplier : 1));
|
||||
}
|
||||
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_7x13B_tr);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr);
|
||||
//canvas_set_font(canvas, FontPrimary);
|
||||
const char* message = "Scanning";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
u8g2_GetDisplayWidth(&canvas->fb) / 2 - canvas_string_width(canvas, message) / 2,
|
||||
55,
|
||||
message);
|
||||
canvas, 128 / 2 - canvas_string_width(canvas, message) / 2, 55, message);
|
||||
} break;
|
||||
case MonitorAnimation: {
|
||||
uint32_t currentTime = furi_get_tick();
|
||||
@@ -407,27 +610,24 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) {
|
||||
canvas_draw_disc(
|
||||
canvas,
|
||||
offsetX + 30,
|
||||
u8g2_GetDisplayHeight(&canvas->fb) / 2 - 7,
|
||||
64 / 2 - 7,
|
||||
5 * (app->m_animtaionCounter == 0 ? mutliplier : 1));
|
||||
canvas_draw_disc(
|
||||
canvas,
|
||||
offsetX + 55,
|
||||
u8g2_GetDisplayHeight(&canvas->fb) / 2 - 7,
|
||||
64 / 2 - 7,
|
||||
5 * (app->m_animtaionCounter == 1 ? mutliplier : 1));
|
||||
canvas_draw_disc(
|
||||
canvas,
|
||||
offsetX + 80,
|
||||
u8g2_GetDisplayHeight(&canvas->fb) / 2 - 7,
|
||||
64 / 2 - 7,
|
||||
5 * (app->m_animtaionCounter == 0 ? mutliplier : 1));
|
||||
|
||||
u8g2_SetFont(&canvas->fb, u8g2_font_7x13B_tr);
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_7x13B_tr);
|
||||
//canvas_set_font(canvas, FontPrimary);
|
||||
const char* message = "Monitor Mode";
|
||||
canvas_draw_str(
|
||||
canvas,
|
||||
u8g2_GetDisplayWidth(&canvas->fb) / 2 - canvas_string_width(canvas, message) / 2,
|
||||
55,
|
||||
message);
|
||||
canvas, 128 / 2 - canvas_string_width(canvas, message) / 2, 55, message);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -179,11 +179,12 @@ void subghz_scene_decode_raw_on_enter(void* context) {
|
||||
furi_string_get_cstr(item_time),
|
||||
subghz_history_get_type_protocol(subghz->history, i));
|
||||
}
|
||||
furi_string_free(item_name);
|
||||
furi_string_free(item_time);
|
||||
subghz_view_receiver_set_idx_menu(subghz->subghz_receiver, subghz->idx_menu_chosen);
|
||||
}
|
||||
|
||||
furi_string_free(item_name);
|
||||
furi_string_free(item_time);
|
||||
|
||||
subghz_scene_receiver_update_statusbar(subghz);
|
||||
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdReceiver);
|
||||
|
||||
@@ -14,7 +14,6 @@ App(
|
||||
"gui.h",
|
||||
"icon_i.h",
|
||||
"elements.h",
|
||||
"canvas_i.h",
|
||||
"view_dispatcher.h",
|
||||
"view_stack.h",
|
||||
"modules/button_menu.h",
|
||||
|
||||
@@ -101,6 +101,11 @@ uint8_t canvas_current_font_height(const Canvas* canvas) {
|
||||
return font_height;
|
||||
}
|
||||
|
||||
uint8_t canvas_current_font_width(const Canvas* canvas) {
|
||||
furi_assert(canvas);
|
||||
return (uint8_t)u8g2_GetMaxCharWidth(&canvas->fb);
|
||||
}
|
||||
|
||||
const CanvasFontParameters* canvas_get_font_params(const Canvas* canvas, Font font) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(font < FontTotalNumber);
|
||||
|
||||
@@ -120,6 +120,14 @@ uint8_t canvas_height(const Canvas* canvas);
|
||||
*/
|
||||
uint8_t canvas_current_font_height(const Canvas* canvas);
|
||||
|
||||
/** Get current font width
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
*
|
||||
* @return width in pixels.
|
||||
*/
|
||||
uint8_t canvas_current_font_width(const Canvas* canvas);
|
||||
|
||||
/** Get font parameters
|
||||
*
|
||||
* @param canvas Canvas instance
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -436,7 +436,11 @@ static bool hid_send_report(uint8_t report_id) {
|
||||
if((hid_semaphore == NULL) || (hid_connected == false)) return false;
|
||||
if((boot_protocol == true) && (report_id != ReportIdKeyboard)) return false;
|
||||
|
||||
furi_check(furi_semaphore_acquire(hid_semaphore, FuriWaitForever) == FuriStatusOk);
|
||||
FuriStatus status = furi_semaphore_acquire(hid_semaphore, HID_INTERVAL * 2);
|
||||
if(status == FuriStatusErrorTimeout) {
|
||||
return false;
|
||||
}
|
||||
furi_check(status == FuriStatusOk);
|
||||
if(hid_connected == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ env.Append(
|
||||
"variant",
|
||||
)
|
||||
),
|
||||
File("u8g2/u8g2.h"),
|
||||
File("xtreme/xtreme.h"),
|
||||
],
|
||||
CPPDEFINES=[
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Callable, List, Optional, Tuple
|
||||
from typing import Callable, List, Optional, Tuple, Union
|
||||
|
||||
|
||||
class FlipperManifestException(Exception):
|
||||
@@ -57,7 +57,7 @@ class FlipperApplication:
|
||||
|
||||
# .fap-specific
|
||||
sources: List[str] = field(default_factory=lambda: ["*.c*"])
|
||||
fap_version: str | Tuple[int] = "0.1"
|
||||
fap_version: Union[str, Tuple[int]] = "0.1"
|
||||
fap_icon: Optional[str] = None
|
||||
fap_libs: List[str] = field(default_factory=list)
|
||||
fap_category: str = ""
|
||||
|
||||
@@ -271,7 +271,13 @@ class Main(App):
|
||||
self.note_dist_component(
|
||||
"update", "tgz", self.get_dist_path(bundle_tgz)
|
||||
)
|
||||
tar.add(bundle_dir, arcname=bundle_dir_name)
|
||||
|
||||
# Strip uid and gid in case of overflow
|
||||
def tar_filter(tarinfo):
|
||||
tarinfo.uid = tarinfo.gid = 0
|
||||
return tarinfo
|
||||
|
||||
tar.add(bundle_dir, arcname=bundle_dir_name, filter=tar_filter)
|
||||
return bundle_result
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user