Merge remote-tracking branch 'origin/dev' into release-candidate
This commit is contained in:
commit
45e78fbdc2
@ -37,7 +37,7 @@
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL (256)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF \
|
||||
(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL / 2)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME 999
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME 999 << 1
|
||||
|
||||
/** SubGhz state */
|
||||
typedef enum {
|
||||
@ -483,7 +483,7 @@ static void subghz_device_cc1101_ext_capture_ISR() {
|
||||
|
||||
subghz_device_cc1101_ext->async_rx.capture_callback(
|
||||
true,
|
||||
LL_TIM_GetCounter(TIM17),
|
||||
LL_TIM_GetCounter(TIM17) << 1,
|
||||
(void*)subghz_device_cc1101_ext->async_rx.capture_callback_context);
|
||||
}
|
||||
} else {
|
||||
@ -493,11 +493,11 @@ static void subghz_device_cc1101_ext_capture_ISR() {
|
||||
|
||||
subghz_device_cc1101_ext->async_rx.capture_callback(
|
||||
false,
|
||||
LL_TIM_GetCounter(TIM17),
|
||||
LL_TIM_GetCounter(TIM17) << 1,
|
||||
(void*)subghz_device_cc1101_ext->async_rx.capture_callback_context);
|
||||
}
|
||||
}
|
||||
LL_TIM_SetCounter(TIM17, 6);
|
||||
LL_TIM_SetCounter(TIM17, 4); //8>>1
|
||||
}
|
||||
|
||||
void subghz_device_cc1101_ext_start_async_rx(
|
||||
@ -512,7 +512,8 @@ void subghz_device_cc1101_ext_start_async_rx(
|
||||
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||
|
||||
// Configure TIM
|
||||
LL_TIM_SetPrescaler(TIM17, 64 - 1);
|
||||
//Set the timer resolution to 2 us
|
||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||
@ -606,7 +607,7 @@ static void subghz_device_cc1101_ext_async_tx_refill(uint32_t* buffer, size_t sa
|
||||
|
||||
uint32_t duration = level_duration_get_duration(ld);
|
||||
furi_assert(duration > 0);
|
||||
*buffer = duration - 1;
|
||||
*buffer = duration >> 1;
|
||||
buffer++;
|
||||
samples--;
|
||||
}
|
||||
@ -692,7 +693,8 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
||||
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||
|
||||
// Configure TIM
|
||||
LL_TIM_SetPrescaler(TIM17, 64 - 1);
|
||||
// Set the timer resolution to 2 us
|
||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||
|
||||
5
applications/external/hid_app/hid.c
vendored
5
applications/external/hid_app/hid.c
vendored
@ -1,7 +1,6 @@
|
||||
#include "hid.h"
|
||||
#include "views.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "HidApp"
|
||||
|
||||
@ -389,8 +388,6 @@ int32_t hid_usb_app(void* p) {
|
||||
|
||||
bt_hid_connection_status_changed_callback(BtStatusConnected, app);
|
||||
|
||||
dolphin_deed(DolphinDeedPluginStart);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
@ -429,8 +426,6 @@ int32_t hid_ble_app(void* p) {
|
||||
furi_hal_bt_start_advertising();
|
||||
bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app);
|
||||
|
||||
dolphin_deed(DolphinDeedPluginStart);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
bt_set_status_changed_callback(app->bt, NULL, NULL);
|
||||
|
||||
@ -60,6 +60,8 @@ typedef enum {
|
||||
InfraredEditModeNone,
|
||||
InfraredEditModeRename,
|
||||
InfraredEditModeDelete,
|
||||
InfraredEditModeMove,
|
||||
InfraredEditModeMoveSelectDest
|
||||
} InfraredEditMode;
|
||||
|
||||
typedef struct {
|
||||
@ -69,6 +71,7 @@ typedef struct {
|
||||
InfraredEditTarget edit_target : 8;
|
||||
InfraredEditMode edit_mode : 8;
|
||||
int32_t current_button_index;
|
||||
int32_t current_button_index_move_orig;
|
||||
uint32_t last_transmit_time;
|
||||
} InfraredAppState;
|
||||
|
||||
|
||||
@ -108,6 +108,21 @@ bool infrared_remote_delete_button(InfraredRemote* remote, size_t index) {
|
||||
return infrared_remote_store(remote);
|
||||
}
|
||||
|
||||
bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest) {
|
||||
furi_assert(index_orig < InfraredButtonArray_size(remote->buttons));
|
||||
furi_assert(index_dest <= InfraredButtonArray_size(remote->buttons));
|
||||
if(index_orig == index_dest) {
|
||||
return true;
|
||||
}
|
||||
InfraredRemoteButton* button;
|
||||
InfraredButtonArray_pop_at(&button, remote->buttons, index_orig);
|
||||
if(index_orig > index_dest)
|
||||
InfraredButtonArray_push_at(remote->buttons, index_dest, button);
|
||||
else
|
||||
InfraredButtonArray_push_at(remote->buttons, index_dest - 1, button);
|
||||
return infrared_remote_store(remote);
|
||||
}
|
||||
|
||||
bool infrared_remote_store(InfraredRemote* remote) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||
|
||||
@ -23,6 +23,7 @@ bool infrared_remote_find_button_by_name(InfraredRemote* remote, const char* nam
|
||||
bool infrared_remote_add_button(InfraredRemote* remote, const char* name, InfraredSignal* signal);
|
||||
bool infrared_remote_rename_button(InfraredRemote* remote, const char* new_name, size_t index);
|
||||
bool infrared_remote_delete_button(InfraredRemote* remote, size_t index);
|
||||
bool infrared_remote_move_button(InfraredRemote* remote, size_t index_orig, size_t index_dest);
|
||||
|
||||
bool infrared_remote_store(InfraredRemote* remote);
|
||||
bool infrared_remote_load(InfraredRemote* remote, FuriString* path);
|
||||
|
||||
@ -7,6 +7,8 @@ ADD_SCENE(infrared, edit_delete_done, EditDeleteDone)
|
||||
ADD_SCENE(infrared, edit_button_select, EditButtonSelect)
|
||||
ADD_SCENE(infrared, edit_rename, EditRename)
|
||||
ADD_SCENE(infrared, edit_rename_done, EditRenameDone)
|
||||
ADD_SCENE(infrared, edit_move, EditMove)
|
||||
ADD_SCENE(infrared, edit_move_done, EditMoveDone)
|
||||
ADD_SCENE(infrared, learn, Learn)
|
||||
ADD_SCENE(infrared, learn_done, LearnDone)
|
||||
ADD_SCENE(infrared, learn_enter_name, LearnEnterName)
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
typedef enum {
|
||||
SubmenuIndexAddButton,
|
||||
SubmenuIndexRenameButton,
|
||||
SubmenuIndexMoveButton,
|
||||
SubmenuIndexDeleteButton,
|
||||
SubmenuIndexRenameRemote,
|
||||
SubmenuIndexDeleteRemote,
|
||||
@ -30,6 +31,12 @@ void infrared_scene_edit_on_enter(void* context) {
|
||||
SubmenuIndexRenameButton,
|
||||
infrared_scene_edit_submenu_callback,
|
||||
context);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Move Button",
|
||||
SubmenuIndexMoveButton,
|
||||
infrared_scene_edit_submenu_callback,
|
||||
context);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Delete Button",
|
||||
@ -74,6 +81,11 @@ bool infrared_scene_edit_on_event(void* context, SceneManagerEvent event) {
|
||||
infrared->app_state.edit_mode = InfraredEditModeRename;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexMoveButton) {
|
||||
infrared->app_state.edit_target = InfraredEditTargetButton;
|
||||
infrared->app_state.edit_mode = InfraredEditModeMove;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexDeleteButton) {
|
||||
infrared->app_state.edit_target = InfraredEditTargetButton;
|
||||
infrared->app_state.edit_mode = InfraredEditModeDelete;
|
||||
|
||||
@ -11,9 +11,23 @@ void infrared_scene_edit_button_select_on_enter(void* context) {
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
|
||||
const char* header = infrared->app_state.edit_mode == InfraredEditModeRename ?
|
||||
"Rename Button:" :
|
||||
"Delete Button:";
|
||||
const char* header = NULL;
|
||||
switch(infrared->app_state.edit_mode) {
|
||||
case InfraredEditModeRename:
|
||||
header = "Rename Button:";
|
||||
break;
|
||||
case InfraredEditModeDelete:
|
||||
header = "Delete Button:";
|
||||
break;
|
||||
case InfraredEditModeMove:
|
||||
header = "Select Button to Move:";
|
||||
break;
|
||||
case InfraredEditModeMoveSelectDest:
|
||||
case InfraredEditModeNone:
|
||||
default:
|
||||
header = "Move Button Before:";
|
||||
break;
|
||||
}
|
||||
submenu_set_header(submenu, header);
|
||||
|
||||
const size_t button_count = infrared_remote_get_button_count(remote);
|
||||
@ -26,7 +40,14 @@ void infrared_scene_edit_button_select_on_enter(void* context) {
|
||||
infrared_scene_edit_button_select_submenu_callback,
|
||||
context);
|
||||
}
|
||||
|
||||
if(infrared->app_state.edit_mode == InfraredEditModeMoveSelectDest) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"-- Move to the end --",
|
||||
button_count,
|
||||
infrared_scene_edit_button_select_submenu_callback,
|
||||
context);
|
||||
}
|
||||
if(button_count && app_state->current_button_index != InfraredButtonIndexNone) {
|
||||
submenu_set_selected_item(submenu, app_state->current_button_index);
|
||||
app_state->current_button_index = InfraredButtonIndexNone;
|
||||
@ -48,6 +69,12 @@ bool infrared_scene_edit_button_select_on_event(void* context, SceneManagerEvent
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditRename);
|
||||
} else if(edit_mode == InfraredEditModeDelete) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditDelete);
|
||||
} else if(edit_mode == InfraredEditModeMove) {
|
||||
app_state->current_button_index_move_orig = event.event;
|
||||
app_state->edit_mode = InfraredEditModeMoveSelectDest;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditButtonSelect);
|
||||
} else if(edit_mode == InfraredEditModeMoveSelectDest) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditMove);
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
103
applications/main/infrared/scenes/infrared_scene_edit_move.c
Normal file
103
applications/main/infrared/scenes/infrared_scene_edit_move.c
Normal file
@ -0,0 +1,103 @@
|
||||
#include "../infrared_i.h"
|
||||
|
||||
static void infrared_scene_edit_move_dialog_result_callback(DialogExResult result, void* context) {
|
||||
Infrared* infrared = context;
|
||||
view_dispatcher_send_custom_event(infrared->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
DialogEx* dialog_ex = infrared->dialog_ex;
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
|
||||
const InfraredEditTarget edit_target = infrared->app_state.edit_target;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
int32_t current_button_index = infrared->app_state.current_button_index_move_orig;
|
||||
furi_assert(current_button_index != InfraredButtonIndexNone);
|
||||
|
||||
dialog_ex_set_header(dialog_ex, "Move Button?", 64, 0, AlignCenter, AlignTop);
|
||||
InfraredRemoteButton* current_button =
|
||||
infrared_remote_get_button(remote, current_button_index);
|
||||
InfraredSignal* signal = infrared_remote_button_get_signal(current_button);
|
||||
|
||||
if(infrared_signal_is_raw(signal)) {
|
||||
const InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
|
||||
infrared_text_store_set(
|
||||
infrared,
|
||||
0,
|
||||
"%s\nRAW\n%ld samples",
|
||||
infrared_remote_button_get_name(current_button),
|
||||
raw->timings_size);
|
||||
|
||||
} else {
|
||||
const InfraredMessage* message = infrared_signal_get_message(signal);
|
||||
infrared_text_store_set(
|
||||
infrared,
|
||||
0,
|
||||
"%s\n%s\nA=0x%0*lX C=0x%0*lX",
|
||||
infrared_remote_button_get_name(current_button),
|
||||
infrared_get_protocol_name(message->protocol),
|
||||
ROUND_UP_TO(infrared_get_protocol_address_length(message->protocol), 4),
|
||||
message->address,
|
||||
ROUND_UP_TO(infrared_get_protocol_command_length(message->protocol), 4),
|
||||
message->command);
|
||||
}
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
dialog_ex_set_text(dialog_ex, infrared->text_store[0], 64, 31, AlignCenter, AlignCenter);
|
||||
dialog_ex_set_icon(dialog_ex, 0, 0, NULL);
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Move");
|
||||
dialog_ex_set_result_callback(dialog_ex, infrared_scene_edit_move_dialog_result_callback);
|
||||
dialog_ex_set_context(dialog_ex, context);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewDialogEx);
|
||||
}
|
||||
|
||||
bool infrared_scene_edit_move_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultLeft) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExResultRight) {
|
||||
bool success = false;
|
||||
InfraredRemote* remote = infrared->remote;
|
||||
InfraredAppState* app_state = &infrared->app_state;
|
||||
const InfraredEditTarget edit_target = app_state->edit_target;
|
||||
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
furi_assert(app_state->current_button_index != InfraredButtonIndexNone);
|
||||
success = infrared_remote_move_button(
|
||||
remote,
|
||||
app_state->current_button_index_move_orig,
|
||||
app_state->current_button_index);
|
||||
app_state->current_button_index_move_orig = InfraredButtonIndexNone;
|
||||
app_state->current_button_index = InfraredButtonIndexNone;
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
|
||||
if(success) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneEditMoveDone);
|
||||
} else {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
UNUSED(infrared);
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
#include "../infrared_i.h"
|
||||
|
||||
void infrared_scene_edit_move_done_on_enter(void* context) {
|
||||
Infrared* infrared = context;
|
||||
Popup* popup = infrared->popup;
|
||||
|
||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
||||
popup_set_header(popup, "Moved", 83, 19, AlignLeft, AlignBottom);
|
||||
|
||||
popup_set_callback(popup, infrared_popup_closed_callback);
|
||||
popup_set_context(popup, context);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewPopup);
|
||||
}
|
||||
|
||||
bool infrared_scene_edit_move_done_on_event(void* context, SceneManagerEvent event) {
|
||||
Infrared* infrared = context;
|
||||
SceneManager* scene_manager = infrared->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InfraredCustomEventTypePopupClosed) {
|
||||
const InfraredEditTarget edit_target = infrared->app_state.edit_target;
|
||||
if(edit_target == InfraredEditTargetButton) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, InfraredSceneRemote);
|
||||
} else if(edit_target == InfraredEditTargetRemote) {
|
||||
const uint32_t possible_scenes[] = {InfraredSceneStart, InfraredSceneRemoteList};
|
||||
if(!scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, possible_scenes, COUNT_OF(possible_scenes))) {
|
||||
view_dispatcher_stop(infrared->view_dispatcher);
|
||||
}
|
||||
} else {
|
||||
furi_assert(0);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void infrared_scene_edit_move_done_on_exit(void* context) {
|
||||
Infrared* infrared = context;
|
||||
UNUSED(infrared);
|
||||
}
|
||||
@ -146,7 +146,7 @@ static void nfc_cli_apdu(Cli* cli, FuriString* args) {
|
||||
resp_size = (tx_rx.rx_bits / 8) * 2;
|
||||
if(!resp_size) {
|
||||
printf("No response\r\n");
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
resp_buffer = malloc(resp_size);
|
||||
uint8_to_hex_chars(tx_rx.rx_data, resp_buffer, resp_size);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#define TAG "U2F"
|
||||
|
||||
#define U2F_DATA_FOLDER ANY_PATH("u2f/")
|
||||
#define U2F_DATA_FOLDER EXT_PATH("u2f/")
|
||||
#define U2F_CERT_FILE U2F_DATA_FOLDER "assets/cert.der"
|
||||
#define U2F_CERT_KEY_FILE U2F_DATA_FOLDER "assets/cert_key.u2f"
|
||||
#define U2F_KEY_FILE U2F_DATA_FOLDER "key.u2f"
|
||||
|
||||
@ -39,7 +39,7 @@ static const DolphinDeedWeight dolphin_deed_weights[] = {
|
||||
|
||||
{1, DolphinAppPlugin}, // DolphinDeedGpioUartBridge
|
||||
|
||||
{1, DolphinAppPlugin}, // DolphinDeedPluginStart
|
||||
{2, DolphinAppPlugin}, // DolphinDeedPluginStart
|
||||
{1, DolphinAppPlugin}, // DolphinDeedPluginGameStart
|
||||
{10, DolphinAppPlugin}, // DolphinDeedPluginGameWin
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <furi.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
/** ByteInput type */
|
||||
struct ByteInput {
|
||||
View* view;
|
||||
};
|
||||
@ -25,7 +26,7 @@ typedef struct {
|
||||
|
||||
bool selected_high_nibble;
|
||||
uint8_t selected_byte;
|
||||
int8_t selected_row; // row -1 - input, row 0 & 1 - keyboard
|
||||
int8_t selected_row; // row -2 - mini_editor, -1 - input, row 0 & 1 - keyboard
|
||||
uint8_t selected_column;
|
||||
uint8_t first_visible_byte;
|
||||
} ByteInputModel;
|
||||
@ -61,11 +62,11 @@ static const ByteInputKey keyboard_keys_row_2[] = {
|
||||
{enter_symbol, 95, 17},
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get row size
|
||||
*
|
||||
* @param row_index Index of row
|
||||
* @return uint8_t Row size
|
||||
/** Get row size
|
||||
*
|
||||
* @param row_index Index of row
|
||||
*
|
||||
* @return uint8_t Row size
|
||||
*/
|
||||
static uint8_t byte_input_get_row_size(uint8_t row_index) {
|
||||
uint8_t row_size = 0;
|
||||
@ -84,11 +85,11 @@ static uint8_t byte_input_get_row_size(uint8_t row_index) {
|
||||
return row_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get row pointer
|
||||
*
|
||||
* @param row_index Index of row
|
||||
* @return const ByteInputKey* Row pointer
|
||||
/** Get row pointer
|
||||
*
|
||||
* @param row_index Index of row
|
||||
*
|
||||
* @return const ByteInputKey* Row pointer
|
||||
*/
|
||||
static const ByteInputKey* byte_input_get_row(uint8_t row_index) {
|
||||
const ByteInputKey* row = NULL;
|
||||
@ -107,12 +108,12 @@ static const ByteInputKey* byte_input_get_row(uint8_t row_index) {
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get text from nibble
|
||||
*
|
||||
* @param byte byte value
|
||||
* @param high_nibble Get from high nibble, otherwise low nibble
|
||||
* @return char nibble text
|
||||
/** Get text from nibble
|
||||
*
|
||||
* @param byte byte value
|
||||
* @param high_nibble Get from high nibble, otherwise low nibble
|
||||
*
|
||||
* @return char nibble text
|
||||
*/
|
||||
static char byte_input_get_nibble_text(uint8_t byte, bool high_nibble) {
|
||||
if(high_nibble) {
|
||||
@ -149,15 +150,20 @@ static char byte_input_get_nibble_text(uint8_t byte, bool high_nibble) {
|
||||
return byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw input box (common view)
|
||||
*
|
||||
* @param canvas
|
||||
* @param model
|
||||
const char num_to_char[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||||
|
||||
/** Draw input box (common view)
|
||||
*
|
||||
* @param canvas The canvas
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) {
|
||||
const uint8_t text_x = 8;
|
||||
const uint8_t text_y = 25;
|
||||
const uint8_t text_y2 = 40;
|
||||
const bool draw_index_line =
|
||||
(model->selected_row == -2) &&
|
||||
(model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes + 1) <= 100);
|
||||
|
||||
elements_slightly_rounded_frame(canvas, 6, 14, 116, 15);
|
||||
|
||||
@ -225,6 +231,27 @@ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) {
|
||||
text_y,
|
||||
byte_input_get_nibble_text(model->bytes[i], false));
|
||||
}
|
||||
|
||||
if(draw_index_line) {
|
||||
canvas_draw_glyph(
|
||||
canvas, text_x + 2 + byte_position * 14, text_y2, num_to_char[(i + 1) / 10]);
|
||||
|
||||
canvas_draw_glyph(
|
||||
canvas, text_x + 8 + byte_position * 14, text_y2, num_to_char[(i + 1) % 10]);
|
||||
}
|
||||
}
|
||||
|
||||
if((model->selected_row == -2) &&
|
||||
(model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes + 1) > 100)) {
|
||||
char str[20];
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
snprintf(str, 20, "Selected index");
|
||||
canvas_draw_str(canvas, text_x, text_y2, str);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
snprintf(str, 20, "%u", (model->selected_byte + 1));
|
||||
canvas_draw_str(canvas, text_x + 75, text_y2, str);
|
||||
}
|
||||
|
||||
if(model->bytes_count - model->first_visible_byte > max_drawable_bytes) {
|
||||
@ -236,11 +263,10 @@ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw input box (selected view)
|
||||
*
|
||||
* @param canvas
|
||||
* @param model
|
||||
/** Draw input box (selected view)
|
||||
*
|
||||
* @param canvas The canvas
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model) {
|
||||
const uint8_t text_x = 7;
|
||||
@ -297,13 +323,12 @@ static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model
|
||||
canvas_invert_color(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set nibble at position
|
||||
*
|
||||
* @param data where to set nibble
|
||||
* @param position byte position
|
||||
* @param value char value
|
||||
* @param high_nibble set high nibble
|
||||
/** Set nibble at position
|
||||
*
|
||||
* @param data where to set nibble
|
||||
* @param position byte position
|
||||
* @param value char value
|
||||
* @param high_nibble set high nibble
|
||||
*/
|
||||
static void byte_input_set_nibble(uint8_t* data, uint8_t position, char value, bool high_nibble) {
|
||||
switch(value) {
|
||||
@ -341,29 +366,28 @@ static void byte_input_set_nibble(uint8_t* data, uint8_t position, char value, b
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief What currently selected
|
||||
*
|
||||
* @return true - keyboard selected, false - input selected
|
||||
/** What currently selected
|
||||
*
|
||||
* @param model The model
|
||||
*
|
||||
* @return true - keyboard selected, false - input selected
|
||||
*/
|
||||
static bool byte_input_keyboard_selected(ByteInputModel* model) {
|
||||
return model->selected_row >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do transition from keyboard
|
||||
*
|
||||
* @param model
|
||||
/** Do transition from keyboard
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_transition_from_keyboard(ByteInputModel* model) {
|
||||
model->selected_row += 1;
|
||||
model->selected_high_nibble = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increase selected byte position
|
||||
*
|
||||
* @param model
|
||||
/** Increase selected byte position
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_inc_selected_byte(ByteInputModel* model) {
|
||||
if(model->selected_byte < model->bytes_count - 1) {
|
||||
@ -379,10 +403,20 @@ static void byte_input_inc_selected_byte(ByteInputModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decrease selected byte position
|
||||
*
|
||||
* @param model
|
||||
static void byte_input_inc_selected_byte_mini(ByteInputModel* model) {
|
||||
if((model->selected_byte < model->bytes_count - 1) || model->selected_high_nibble) {
|
||||
if(!model->selected_high_nibble) {
|
||||
model->selected_high_nibble = !model->selected_high_nibble; //-V547
|
||||
byte_input_inc_selected_byte(model);
|
||||
} else {
|
||||
model->selected_high_nibble = !model->selected_high_nibble; //-V547
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Decrease selected byte position
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_dec_selected_byte(ByteInputModel* model) {
|
||||
if(model->selected_byte > 0) {
|
||||
@ -397,10 +431,20 @@ static void byte_input_dec_selected_byte(ByteInputModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call input callback
|
||||
*
|
||||
* @param model
|
||||
static void byte_input_dec_selected_byte_mini(ByteInputModel* model) {
|
||||
if(model->selected_byte > 0 || !model->selected_high_nibble) {
|
||||
if(model->selected_high_nibble) {
|
||||
model->selected_high_nibble = !model->selected_high_nibble; //-V547
|
||||
byte_input_dec_selected_byte(model);
|
||||
} else {
|
||||
model->selected_high_nibble = !model->selected_high_nibble; //-V547
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Call input callback
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_call_input_callback(ByteInputModel* model) {
|
||||
if(model->input_callback != NULL) {
|
||||
@ -408,10 +452,9 @@ static void byte_input_call_input_callback(ByteInputModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call changed callback
|
||||
*
|
||||
* @param model
|
||||
/** Call changed callback
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_call_changed_callback(ByteInputModel* model) {
|
||||
if(model->changed_callback != NULL) {
|
||||
@ -419,8 +462,9 @@ static void byte_input_call_changed_callback(ByteInputModel* model) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear selected byte
|
||||
/** Clear selected byte
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
|
||||
static void byte_input_clear_selected_byte(ByteInputModel* model) {
|
||||
@ -430,36 +474,55 @@ static void byte_input_clear_selected_byte(ByteInputModel* model) {
|
||||
byte_input_call_changed_callback(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle up button
|
||||
*
|
||||
* @param model
|
||||
/** Handle up button
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_handle_up(ByteInputModel* model) {
|
||||
if(model->selected_row > -1) {
|
||||
if(model->selected_row > -2) {
|
||||
model->selected_row -= 1;
|
||||
} else if(model->selected_row == -2) {
|
||||
if(!model->selected_high_nibble) {
|
||||
model->bytes[model->selected_byte] = (model->bytes[model->selected_byte] & 0xF0) |
|
||||
((model->bytes[model->selected_byte] + 1) & 0x0F);
|
||||
} else {
|
||||
model->bytes[model->selected_byte] =
|
||||
((model->bytes[model->selected_byte] + 0x10) & 0xF0) |
|
||||
(model->bytes[model->selected_byte] & 0x0F);
|
||||
}
|
||||
byte_input_call_changed_callback(model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle down button
|
||||
*
|
||||
* @param model
|
||||
/** Handle down button
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_handle_down(ByteInputModel* model) {
|
||||
if(byte_input_keyboard_selected(model)) {
|
||||
if(model->selected_row < keyboard_row_count - 1) {
|
||||
model->selected_row += 1;
|
||||
if(model->selected_row != -2) {
|
||||
if(byte_input_keyboard_selected(model)) {
|
||||
if(model->selected_row < keyboard_row_count - 1) {
|
||||
model->selected_row += 1;
|
||||
}
|
||||
} else {
|
||||
byte_input_transition_from_keyboard(model);
|
||||
}
|
||||
} else {
|
||||
byte_input_transition_from_keyboard(model);
|
||||
if(!model->selected_high_nibble) {
|
||||
model->bytes[model->selected_byte] = (model->bytes[model->selected_byte] & 0xF0) |
|
||||
((model->bytes[model->selected_byte] - 1) & 0x0F);
|
||||
} else {
|
||||
model->bytes[model->selected_byte] =
|
||||
((model->bytes[model->selected_byte] - 0x10) & 0xF0) |
|
||||
(model->bytes[model->selected_byte] & 0x0F);
|
||||
}
|
||||
byte_input_call_changed_callback(model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle left button
|
||||
*
|
||||
* @param model
|
||||
/** Handle left button
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_handle_left(ByteInputModel* model) {
|
||||
if(byte_input_keyboard_selected(model)) {
|
||||
@ -469,14 +532,17 @@ static void byte_input_handle_left(ByteInputModel* model) {
|
||||
model->selected_column = byte_input_get_row_size(model->selected_row) - 1;
|
||||
}
|
||||
} else {
|
||||
byte_input_dec_selected_byte(model);
|
||||
if(model->selected_row != -2) {
|
||||
byte_input_dec_selected_byte(model);
|
||||
} else {
|
||||
byte_input_dec_selected_byte_mini(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle right button
|
||||
*
|
||||
* @param model
|
||||
/** Handle right button
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_handle_right(ByteInputModel* model) {
|
||||
if(byte_input_keyboard_selected(model)) {
|
||||
@ -486,14 +552,17 @@ static void byte_input_handle_right(ByteInputModel* model) {
|
||||
model->selected_column = 0;
|
||||
}
|
||||
} else {
|
||||
byte_input_inc_selected_byte(model);
|
||||
if(model->selected_row != -2) {
|
||||
byte_input_inc_selected_byte(model);
|
||||
} else {
|
||||
byte_input_inc_selected_byte_mini(model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle OK button
|
||||
*
|
||||
* @param model
|
||||
/** Handle OK button
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_handle_ok(ByteInputModel* model) {
|
||||
if(byte_input_keyboard_selected(model)) {
|
||||
@ -514,16 +583,17 @@ static void byte_input_handle_ok(ByteInputModel* model) {
|
||||
}
|
||||
byte_input_call_changed_callback(model);
|
||||
}
|
||||
} else if(model->selected_row == -2) {
|
||||
byte_input_call_input_callback(model);
|
||||
} else {
|
||||
byte_input_transition_from_keyboard(model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draw callback
|
||||
*
|
||||
* @param canvas
|
||||
* @param _model
|
||||
/** Draw callback
|
||||
*
|
||||
* @param canvas The canvas
|
||||
* @param _model The model
|
||||
*/
|
||||
static void byte_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
ByteInputModel* model = _model;
|
||||
@ -541,80 +611,89 @@ static void byte_input_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
byte_input_draw_input(canvas, model);
|
||||
}
|
||||
|
||||
for(uint8_t row = 0; row < keyboard_row_count; row++) {
|
||||
const uint8_t column_count = byte_input_get_row_size(row);
|
||||
const ByteInputKey* keys = byte_input_get_row(row);
|
||||
if(model->selected_row == -2) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_icon(canvas, 3, 52, &I_Pin_back_arrow_10x8);
|
||||
canvas_draw_str_aligned(canvas, 16, 60, AlignLeft, AlignBottom, "back to keyboard");
|
||||
} else {
|
||||
// Draw keyboard
|
||||
for(uint8_t row = 0; row < keyboard_row_count; row++) {
|
||||
const uint8_t column_count = byte_input_get_row_size(row);
|
||||
const ByteInputKey* keys = byte_input_get_row(row);
|
||||
|
||||
for(size_t column = 0; column < column_count; column++) {
|
||||
if(keys[column].value == enter_symbol) {
|
||||
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);
|
||||
}
|
||||
} else if(keys[column].value == backspace_symbol) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
if(model->selected_row == row && model->selected_column == column) {
|
||||
for(size_t column = 0; column < column_count; column++) {
|
||||
if(keys[column].value == enter_symbol) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x - 3,
|
||||
keyboard_origin_y + keys[column].y - 10,
|
||||
11,
|
||||
13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else if(model->selected_row == -1 && row == 0 && model->selected_column == column) {
|
||||
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);
|
||||
}
|
||||
} else if(keys[column].value == backspace_symbol) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_frame(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x - 3,
|
||||
keyboard_origin_y + keys[column].y - 10,
|
||||
11,
|
||||
13);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
if(model->selected_row == row && model->selected_column == column) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x - 3,
|
||||
keyboard_origin_y + keys[column].y - 10,
|
||||
11,
|
||||
13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else if(
|
||||
model->selected_row == -1 && row == 0 &&
|
||||
model->selected_column == column) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_frame(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x - 3,
|
||||
keyboard_origin_y + keys[column].y - 10,
|
||||
11,
|
||||
13);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
keys[column].value);
|
||||
canvas_draw_glyph(
|
||||
canvas,
|
||||
keyboard_origin_x + keys[column].x,
|
||||
keyboard_origin_y + keys[column].y,
|
||||
keys[column].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Input callback
|
||||
*
|
||||
* @param event
|
||||
* @param context
|
||||
* @return true
|
||||
* @return false
|
||||
/** Input callback
|
||||
*
|
||||
* @param event The event
|
||||
* @param context The context
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
static bool byte_input_view_input_callback(InputEvent* event, void* context) {
|
||||
ByteInput* byte_input = context;
|
||||
@ -656,6 +735,20 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
if(event->type == InputTypeShort && event->key == InputKeyBack) {
|
||||
// Back to keyboard
|
||||
with_view_model(
|
||||
byte_input->view,
|
||||
ByteInputModel * model,
|
||||
{
|
||||
if(model->selected_row == -2) {
|
||||
model->selected_row += 1;
|
||||
consumed = true;
|
||||
};
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
if((event->type == InputTypeLong || event->type == InputTypeRepeat) &&
|
||||
event->key == InputKeyBack) {
|
||||
with_view_model(
|
||||
@ -669,10 +762,9 @@ static bool byte_input_view_input_callback(InputEvent* event, void* context) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all input-related data in model
|
||||
*
|
||||
* @param model ByteInputModel
|
||||
/** Reset all input-related data in model
|
||||
*
|
||||
* @param model The model
|
||||
*/
|
||||
static void byte_input_reset_model_input_data(ByteInputModel* model) {
|
||||
model->bytes = NULL;
|
||||
@ -684,11 +776,6 @@ static void byte_input_reset_model_input_data(ByteInputModel* model) {
|
||||
model->first_visible_byte = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocate and initialize byte input. This byte input is used to enter bytes.
|
||||
*
|
||||
* @return ByteInput instance pointer
|
||||
*/
|
||||
ByteInput* byte_input_alloc() {
|
||||
ByteInput* byte_input = malloc(sizeof(ByteInput));
|
||||
byte_input->view = view_alloc();
|
||||
@ -712,38 +799,17 @@ ByteInput* byte_input_alloc() {
|
||||
return byte_input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize and free byte input
|
||||
*
|
||||
* @param byte_input Byte input instance
|
||||
*/
|
||||
void byte_input_free(ByteInput* byte_input) {
|
||||
furi_assert(byte_input);
|
||||
view_free(byte_input->view);
|
||||
free(byte_input);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get byte input view
|
||||
*
|
||||
* @param byte_input byte input instance
|
||||
* @return View instance that can be used for embedding
|
||||
*/
|
||||
View* byte_input_get_view(ByteInput* byte_input) {
|
||||
furi_assert(byte_input);
|
||||
return byte_input->view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize and free byte input
|
||||
*
|
||||
* @param byte_input byte input instance
|
||||
* @param input_callback input callback fn
|
||||
* @param changed_callback changed callback fn
|
||||
* @param callback_context callback context
|
||||
* @param bytes buffer to use
|
||||
* @param bytes_count buffer length
|
||||
*/
|
||||
void byte_input_set_result_callback(
|
||||
ByteInput* byte_input,
|
||||
ByteInputCallback input_callback,
|
||||
@ -765,12 +831,6 @@ void byte_input_set_result_callback(
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set byte input header text
|
||||
*
|
||||
* @param byte_input byte input instance
|
||||
* @param text text to be shown
|
||||
*/
|
||||
void byte_input_set_header_text(ByteInput* byte_input, const char* text) {
|
||||
with_view_model(
|
||||
byte_input->view, ByteInputModel * model, { model->header = text; }, true);
|
||||
|
||||
@ -6,7 +6,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define RECORD_LOADER "loader"
|
||||
#define LOADER_APPLICATIONS_NAME "Applications"
|
||||
#define LOADER_APPLICATIONS_NAME "Apps"
|
||||
|
||||
typedef struct Loader Loader;
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_holder.h>
|
||||
#include <gui/modules/loading.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "LoaderApplications"
|
||||
|
||||
@ -119,6 +120,8 @@ static void loader_pubsub_callback(const void* message, void* context) {
|
||||
static void loader_applications_start_app(LoaderApplicationsApp* app) {
|
||||
const char* name = furi_string_get_cstr(app->fap_path);
|
||||
|
||||
dolphin_deed(DolphinDeedPluginStart);
|
||||
|
||||
// load app
|
||||
FuriThreadId thread_id = furi_thread_get_current_id();
|
||||
FuriPubSubSubscription* subscription =
|
||||
|
||||
@ -14,7 +14,7 @@ static void loader_cli_print_usage() {
|
||||
}
|
||||
|
||||
static void loader_cli_list() {
|
||||
printf("Applications:\r\n");
|
||||
printf("Apps:\r\n");
|
||||
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
|
||||
printf("\t%s\r\n", FLIPPER_APPS[i].name);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include <input/input.h>
|
||||
#include <gui/gui_i.h>
|
||||
#include <u8g2_glue.h>
|
||||
|
||||
#include <lib/toolbox/float_tools.h>
|
||||
#include "notification.h"
|
||||
#include "notification_messages.h"
|
||||
#include "notification_app.h"
|
||||
@ -104,7 +104,10 @@ static void notification_reset_notification_led_layer(NotificationLedLayer* laye
|
||||
furi_hal_light_set(layer->light, layer->value[LayerInternal]);
|
||||
}
|
||||
|
||||
static void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) {
|
||||
static void notification_reset_notification_layer(
|
||||
NotificationApp* app,
|
||||
uint8_t reset_mask,
|
||||
float display_brightness_set) {
|
||||
if(reset_mask & reset_blink_mask) {
|
||||
furi_hal_light_blink_stop();
|
||||
}
|
||||
@ -124,6 +127,9 @@ static void notification_reset_notification_layer(NotificationApp* app, uint8_t
|
||||
notification_sound_off();
|
||||
}
|
||||
if(reset_mask & reset_display_mask) {
|
||||
if(!float_is_equal(display_brightness_set, app->settings.display_brightness)) {
|
||||
furi_hal_light_set(LightBacklight, app->settings.display_brightness * 0xFF);
|
||||
}
|
||||
furi_timer_start(app->display_timer, notification_settings_display_off_delay_ticks(app));
|
||||
}
|
||||
}
|
||||
@ -212,13 +218,14 @@ static void notification_process_notification_message(
|
||||
notification_apply_notification_led_layer(
|
||||
&app->display,
|
||||
notification_message->data.led.value * display_brightness_setting);
|
||||
reset_mask |= reset_display_mask;
|
||||
} else {
|
||||
reset_mask &= ~reset_display_mask;
|
||||
notification_reset_notification_led_layer(&app->display);
|
||||
if(furi_timer_is_running(app->display_timer)) {
|
||||
furi_timer_stop(app->display_timer);
|
||||
}
|
||||
}
|
||||
reset_mask |= reset_display_mask;
|
||||
break;
|
||||
case NotificationMessageTypeLedDisplayBacklightEnforceOn:
|
||||
furi_assert(app->display_led_lock < UINT8_MAX);
|
||||
@ -370,7 +377,7 @@ static void notification_process_notification_message(
|
||||
}
|
||||
|
||||
if(reset_notifications) {
|
||||
notification_reset_notification_layer(app, reset_mask);
|
||||
notification_reset_notification_layer(app, reset_mask, display_brightness_setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -87,6 +87,7 @@ static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* mess
|
||||
message, furi_hal_version_get_mic_id(), 63, 27, AlignLeft, AlignCenter);
|
||||
result = dialog_message_show(dialogs, message);
|
||||
dialog_message_set_icon(message, NULL, 0, 0);
|
||||
dialog_message_set_text(message, NULL, 0, 0, AlignLeft, AlignTop);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -172,8 +173,6 @@ const AboutDialogScreen about_screens[] = {
|
||||
hw_version_screen,
|
||||
fw_version_screen};
|
||||
|
||||
const size_t about_screens_count = sizeof(about_screens) / sizeof(AboutDialogScreen);
|
||||
|
||||
int32_t about_settings_app(void* p) {
|
||||
UNUSED(p);
|
||||
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
@ -194,7 +193,7 @@ int32_t about_settings_app(void* p) {
|
||||
view_dispatcher_switch_to_view(view_dispatcher, empty_screen_index);
|
||||
|
||||
while(1) {
|
||||
if(screen_index >= about_screens_count - 1) {
|
||||
if(screen_index >= COUNT_OF(about_screens) - 1) {
|
||||
dialog_message_set_buttons(message, "Back", NULL, NULL);
|
||||
} else {
|
||||
dialog_message_set_buttons(message, "Back", NULL, "Next");
|
||||
@ -209,7 +208,7 @@ int32_t about_settings_app(void* p) {
|
||||
screen_index--;
|
||||
}
|
||||
} else if(screen_result == DialogMessageButtonRight) {
|
||||
if(screen_index < about_screens_count) {
|
||||
if(screen_index < COUNT_OF(about_screens) - 1) {
|
||||
screen_index++;
|
||||
}
|
||||
} else if(screen_result == DialogMessageButtonBack) {
|
||||
|
||||
@ -7,10 +7,10 @@
|
||||
|
||||
#define APPS_COUNT (FLIPPER_APPS_COUNT + FLIPPER_EXTERNAL_APPS_COUNT)
|
||||
|
||||
#define EXTERNAL_BROWSER_NAME ("Applications")
|
||||
#define EXTERNAL_BROWSER_NAME ("Apps")
|
||||
#define EXTERNAL_BROWSER_INDEX (APPS_COUNT + 1)
|
||||
|
||||
#define EXTERNAL_APPLICATION_NAME ("[External Application]")
|
||||
#define EXTERNAL_APPLICATION_NAME ("[Select App]")
|
||||
#define EXTERNAL_APPLICATION_INDEX (APPS_COUNT + 2)
|
||||
|
||||
#define PRESELECTED_SPECIAL 0xffffffff
|
||||
|
||||
BIN
assets/resources/badusb/assets/layouts/fr-CA.kl
Normal file
BIN
assets/resources/badusb/assets/layouts/fr-CA.kl
Normal file
Binary file not shown.
@ -581,3 +581,40 @@ type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 3204 9889 537 1587 491 529 512 544 489 545 489 1573 510 530 511 543 491 552 490 538 511 543 491 543 491 532 509 543 491 1587 489 537 512 543 491 1577 490 543 491 543 491 544 489 543 491 1586 489 544 490 1587 489 539 510 543 491 543 491 1586 490
|
||||
#
|
||||
# Model: Daikin FTXC35DV1B
|
||||
name: Off
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 530 315 532 314 532 314 532 314 532 314 506 340 561 24780 3568 1647 507 1213 535 313 534 340 506 340 506 1212 507 339 507 339 506 339 506 339 506 1214 505 341 504 1215 505 1216 504 343 503 1217 503 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1219 501 345 501 344 502 345 501 1219 501 1219 501 345 501 344 502 344 502 345 501 344 502 345 501 344 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 501 1219 501 34807 3563 1652 502 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1219 501 344 502 1218 502 1219 501 344 502 1219 501 1218 502 1219 501 1219 501 1219 501 345 501 344 502 1219 501 345 501 344 502 345 501 344 502 344 502 345 501 345 501 345 501 344 502 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1219 501 345 501 345 501 1219 501 1219 501 345 501 1219 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1220 500 346 500 345 501 346 500 346 500 34806 3564 1652 502 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1219 501 1218 502 344 502 345 501 1219 501 345 501 344 502 345 501 344 502 344 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 346 500 345 501 345 501 345 501 345 501 346 500 346 500 346 500 346 500 346 500 1220 499 346 500 1220 499 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 346 500 1221 499 1221 499 1221 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 1245 475 1222 498 1245 475 371 475 348 498 348 498 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 372 474 372 474 372 474 371 475 371 475 1246 474 371 475 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 371 475 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1246 474 1246 473 372 474 372 474 1246 474 372 474
|
||||
#
|
||||
name: Dh
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 536 339 507 311 535 312 534 312 534 312 534 339 507 24807 3710 1507 594 1156 563 305 543 304 542 304 570 1126 592 304 515 304 542 304 542 304 542 1155 564 304 541 1158 505 1215 505 342 504 1217 503 1217 503 1218 502 1218 502 1218 502 344 502 343 503 1218 502 343 503 343 503 344 502 344 502 344 502 344 502 344 502 343 503 343 503 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 1218 502 1218 501 344 502 1218 502 344 502 1218 502 1218 502 34800 3564 1651 503 1217 503 343 503 344 502 343 503 1217 503 343 503 343 503 344 502 344 502 1218 502 344 502 1217 503 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 344 502 1218 502 1218 502 344 502 1218 502 1219 501 1219 501 345 501 344 502 344 502 344 502 344 502 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 34805 3565 1650 503 1216 503 343 503 343 503 344 502 1217 503 343 503 344 502 343 503 343 503 1217 503 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 1218 502 344 502 1218 501 344 502 344 502 344 502 345 501 344 502 345 501 344 502 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 346 500 345 501 345 501 346 500 370 476 346 500 346 500 346 500 370 476 346 500 346 500 346 500 346 500 1221 499 1244 476 1244 476 370 476 346 500 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1244 476 1244 476 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1244 476 370 476 1245 475 370 476 371 475 370 476 1245 475 1245 475 371 475 371 475 370 476 370 476 370 476 370 476 370 476 371 475 370 476 371 475 371 475 371 475 371 475 370 476 371 475 371 475 371 475 1245 475 1245 475 1245 475 371 475 371 475 1245 475 371 475
|
||||
#
|
||||
name: Cool_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 507 340 559 306 487 341 530 315 531 313 561 305 541 24776 3569 1646 508 1212 537 340 506 340 506 340 506 1213 507 339 507 339 506 339 506 340 505 1214 505 341 504 1215 504 1216 503 343 503 1217 502 1218 502 1218 502 1218 502 1218 501 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1219 501 1218 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 501 1219 501 34800 3563 1652 502 1217 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 501 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 345 501 345 501 344 502 345 501 344 502 345 501 345 501 345 501 344 502 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 1219 501 345 501 345 501 1219 501 1219 501 345 501 1219 500 1219 500 1219 500 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1220 500 346 500 346 500 346 500 346 500 34808 3564 1652 503 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 345 501 344 502 1218 502 345 501 1218 502 1219 501 344 502 1219 501 1219 501 1219 501 1219 501 1219 501 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 500 345 501 345 501 1219 500 1219 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1219 501 346 500 346 500 345 501 345 501 346 500 346 500 346 500 345 501 346 500 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 346 500 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 347 499 346 500 1221 499 1245 475 1221 499 347 499 347 499 347 499 348 498 347 499 348 498 348 498 371 475 348 498 1222 498 1245 475 1245 475 348 498 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 372 474 372 474 372 474 371 475 1245 474 372 474 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 372 474 372 474 372 474 1247 473 1247 473
|
||||
#
|
||||
name: Cool_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 533 311 535 312 534 312 534 313 533 310 536 312 534 24804 3705 1509 593 1129 590 305 542 305 542 305 569 1127 590 304 514 305 541 304 542 305 541 1155 564 305 540 1157 561 1159 504 341 504 1217 503 1217 503 1217 503 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 345 501 1218 502 1218 502 1218 502 344 502 1219 501 345 501 1219 501 1219 501 34806 3565 1650 503 1217 502 343 503 343 503 343 503 1217 503 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1219 501 344 502 1218 502 344 502 1219 501 1218 501 345 501 1218 501 1219 501 1218 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 34805 3565 1651 503 1217 502 343 503 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 1218 502 1219 501 1218 502 345 501 344 502 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 346 500 346 500 345 501 345 501 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 1221 499 1221 498 346 500 346 500 370 476 346 500 347 499 347 499 370 476 370 476 370 476 1244 476 1244 476 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 371 475 370 476 370 476 370 476 371 475 370 476 370 476 370 476 370 476 1244 476 371 475 1245 475 370 476 371 475 371 475 1245 475 1245 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 476 371 475 1245 475 1245 475 371 475 371 475 1246 474 1245 475
|
||||
#
|
||||
name: Heat_lo
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 535 313 533 311 535 311 535 312 534 312 534 313 533 24805 3711 1506 592 1129 592 305 543 305 540 305 569 1126 592 304 514 304 542 304 541 304 485 1213 507 340 506 1214 506 1215 505 342 504 1217 503 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 503 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 503 344 502 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 502 1219 502 34818 3566 1651 503 1217 503 343 503 344 502 344 502 1218 502 344 502 344 502 344 502 344 503 1218 502 344 502 1218 503 1218 502 344 502 1218 502 1218 503 1218 503 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 345 501 344 502 344 502 1219 501 345 501 345 502 1219 501 345 501 1219 502 1219 502 1219 502 344 502 1219 501 1219 502 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 345 501 1219 501 345 501 345 501 345 501 34812 3566 1651 503 1217 503 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 503 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1219 501 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 345 501 344 502 345 501 345 501 1219 502 345 501 345 501 1219 502 345 501 345 501 1219 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 502 345 501 345 501 345 501 346 500 345 501 345 501 345 501 345 501 345 501 1220 500 346 500 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 346 500 347 499 347 499 370 476 1244 476 1221 499 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1245 475 1245 476 1245 475 371 475 370 476 370 476 371 475 371 475 370 476 370 476 371 475 371 476 370 476 370 476 371 475 371 475 371 475 371 475 371 475 1245 475 371 475 1245 475 371 475 371 475 371 475 1245 475 1245 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 476 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 1245 475 1245 475 1245 475 371 475 1245 475 1246 474
|
||||
#
|
||||
name: Heat_hi
|
||||
type: raw
|
||||
frequency: 38000
|
||||
duty_cycle: 0.330000
|
||||
data: 535 314 532 314 533 313 533 312 534 313 533 312 508 24840 3569 1647 508 1213 536 342 505 342 504 341 505 1214 506 340 506 340 506 340 505 340 506 1214 506 341 504 1216 504 1217 503 343 503 1218 502 1219 501 1219 502 1219 502 1219 502 345 502 344 502 1219 502 345 501 345 502 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 1219 502 345 501 1219 501 345 502 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 500 1219 501 1220 500 345 501 1220 500 345 501 1220 501 1220 500 34815 3564 1653 502 1218 502 344 502 345 501 344 502 1219 501 345 501 345 501 345 501 345 501 1219 502 345 501 1219 502 1220 501 345 502 1219 501 1219 502 1219 501 1219 502 1219 502 345 501 345 501 1220 501 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 345 502 345 501 345 501 1220 501 345 501 345 501 345 501 345 501 1220 500 345 501 346 501 1220 500 1220 501 345 501 345 501 346 500 1220 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 345 501 346 500 345 501 1220 500 346 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 34816 3565 1653 502 1219 501 344 502 345 501 345 501 1219 502 345 501 345 502 345 501 345 501 1219 501 345 501 1219 502 1219 501 345 501 1219 502 1219 501 1219 501 1219 501 1219 501 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 501 346 501 345 501 1220 501 346 500 346 500 1220 500 346 500 345 501 346 500 1220 500 1220 500 1220 501 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 346 500 1220 500 347 499 346 500 346 500 346 500 347 499 347 499 346 500 346 500 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 1222 498 1222 499 1222 498 347 499 348 498 348 498 347 499 371 475 348 498 348 498 348 498 371 475 1222 498 1246 474 1246 474 372 475 371 475 372 474 372 474 348 498 371 475 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1247 473 372 474 1246 474 1246 474 1246 474
|
||||
|
||||
@ -328,3 +328,52 @@ type: parsed
|
||||
protocol: NECext
|
||||
address: 30 FC 00 00
|
||||
command: 0C F3 00 00
|
||||
#
|
||||
# Model: Panasonic SA-PM193
|
||||
name: Power
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: AC 02 20 00
|
||||
command: D1 03 00 00
|
||||
# CD play/pause, tape play also exists but probably less commonly used
|
||||
name: Play
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: AA 02 20 00
|
||||
command: A0 00 00 00
|
||||
# same as above
|
||||
name: Pause
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: AA 02 20 00
|
||||
command: A0 00 00 00
|
||||
#
|
||||
name: Vol_up
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: A0 02 20 00
|
||||
command: 00 02 00 00
|
||||
#
|
||||
name: Vol_dn
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: A0 02 20 00
|
||||
command: 10 02 00 00
|
||||
#
|
||||
name: Next
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: AC 02 20 01
|
||||
command: A1 00 00 00
|
||||
#
|
||||
name: Prev
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: AC 02 20 01
|
||||
command: 91 00 00 00
|
||||
#
|
||||
name: Mute
|
||||
type: parsed
|
||||
protocol: Kaseikyo
|
||||
address: A0 02 20 00
|
||||
command: 20 03 00 00
|
||||
|
||||
@ -1,56 +1,57 @@
|
||||
Filetype: Flipper SubGhz Keystore File
|
||||
Version: 0
|
||||
Encryption: 1
|
||||
IV: 41 84 34 43 84 1D 43 04 45 44 34 38 41 24 3E 74
|
||||
8C5AEF725F0620DB3952B40BB8E76A815BCEE1D1B92F7E8E8E63D1894F1C7FD0
|
||||
1DFF1D6A322D6B3D8AD7C594A02462AADE723D417B9233585526982F08187DAA
|
||||
0A9184F15D4A5589DDDA6422063BACD58580661CFE60EE600D87F73F0CB5013E
|
||||
6E56802DAA049C3DFDEDC90432A0E694A172C369EBECD136F4C911B979AA098D
|
||||
A659716B51053604059F7FC3651D6A153F5EAB1852F95B20C44C41A7889A0DE91A078B63E3C311280C4315F0A3C8BA1F
|
||||
A315170EDC51627157725D9A96490DB75EBF8232957FBA313C03B2BA2884EA85
|
||||
DEAB3C2C2E2DC76FE45AEBAC7EBFB478CECCD970A63B8DE2024FBFDCCBD1B26E
|
||||
7BBFC36CBA77468B4624C6B685610877D53985C985DAD8EFE47527EB7C7260CD
|
||||
879EE18B314ED4F3F548B41176099176FB97F4F1A062481C935B2DDFBCE2FE4D
|
||||
493372D7D47A96A66305DFDC8A915EB651620881AE1D603B7E9605E004C04CA9
|
||||
F80AAA4C447F8E8C0B039DDAECF9126119C32FF164118780BE268E326A8CBF8010DE2EBF94033CEAC39815D6A8958CF4
|
||||
41C1393A039E665F6A53A5E5D1C105008BD14D9755751545A667860C39B2E39AA47306E76E2BA7DDDAA2A286FDB58D23
|
||||
34853A4CDE42CB80045E641AB4800C86C1CF6907EAAFA399156CCC727A008584
|
||||
D0783A34BD6A36D31BFF5F70FA1116CAE48EF02716D80481AE406DABB3C3400E
|
||||
0BB3582605434CF2A5D74A27773B88DA331B6033C444837E9F7A155897258B03
|
||||
E4E71F3EB290B9436FFF0FDADA468BE37D964E89BE8D9971A14776F821822769
|
||||
744AA59D129C892120B5DAB81C8A3D573B0AD80EF0708C1B9ECF13DA60CECA07DC0591A08611DB4D3A8B7C70994D5DEF
|
||||
716F9F8D5D2C697BC4183EFCC97E52D08ECA07B613A0F389C801F65803DFF4A4
|
||||
560262DA8489D2C18C8D97E314DC663403AFE4DE9DCB6D453087D2BFBD36532D
|
||||
9E31F7152C50B6940EE3E3894C98F75702C7897F702B48E5C9B54B6E25083641AD2E521267505066C7E5BAB7F6CF1433
|
||||
6630EDA18A6E58BD395792CCC656DD10CD9C5DD2B1949FE677122FA39A53C724E79C0D0752A3A39A03407BBA2282185E
|
||||
00D15A06F5DD82A4B926B78809CC4D129AAFA9A92B0A81568F255D15697FE0FD
|
||||
29FF9A4F5346ABEE8FEDE034988F87FCD29EA747735898F1E7207EF74FAB71A8
|
||||
C0E8EB6AE6F77EE38DF2AB1B7742E34ED5236F3D8E964845E66762A4675AA21F
|
||||
00FC4C459DC4CE92B62D0AC2546F9FBBE0893F84D2AF0A20ED462A5EAE63DE3B
|
||||
E92EF482A40CEEFC8339BBB713BBC452A266A09B2645EDEB12716544B2DB9B09
|
||||
D7D9C5C757831BCE2FF1DB25A080D77769FB36A1F3F48F4361418A0A45609280
|
||||
C19246F52AE1EE5CE968CED52F642D9CD78B020029632FE83C49C657D23ED075
|
||||
FEE3C05432FB3860D5D28562323F5D1B053B8F3ADCD416BD0C4645F6F4D43DCF
|
||||
D780A4AADD0205E0BACDCC9AF46ED259E0946C5DA888C341BFE96E09A87CCCFA
|
||||
CE3C13CFA08E532B637FDB707E29548D57EE92EAEF6516C3D67E9D36FCD59CF9
|
||||
5E88CE71258CB0D91631FEB41C9A2F47AE0FF4810A9A1EDF3F308BBDE6944D5E
|
||||
1531F4107FC64810BA5DB5E46C7B9AD61531AF5430E137B7688109FBC06B6221
|
||||
68050A39C0B302E0B713FAAC5F829C79AB30E18B1D982A94005DBAC7CCFB95379A619C0B9F7409C44D19FF2C5E8E4546
|
||||
3F73E8BA22C602280496EF8E88E2CAA9EC442E3B3083B684942DBF9CB5121241
|
||||
FA1FCD7C9182FAE8FFF4E88433AE68F66076B3BDFF8AD0BF5CEA43870082E9BE
|
||||
DFF7DD2678C03401656B093BF7AC7E033F15FD0F30188E48A62045740B423699
|
||||
371BCFF653E7811D99C048A1A39921AAA563E06AC86CB3D2F392C2C955A1ABD0
|
||||
F4F1766DEAEDE934478208B9EB3050326D9FFCC001C73EEE93407D8B12CD49E4
|
||||
A241C9FC62DDF67D645936245FAFFE2A42C86151F484B7BCE5410E8F36FC87901D3AC4E40334E08FFFC2AD676E490D94
|
||||
3566A94A9C0479E0C4387D9137375ADF2C921504364F3903F198D6757CDFD21B
|
||||
7274E1B5A6445FDC29C355D550E981C17F349BC4A14251B3B51BC96FC334FBCA
|
||||
04EEA5EDD9B3BC3E0638E53A5561DC8BF761D615A64D435BD31A94AF2650159E
|
||||
B84818CC1695FE8B731CD653D0679D1AAA0578C0B06AD1E3510785B2DE20841C
|
||||
4121343D6B79E38C06DD038D770D76D10336AFF47ED0D0DCDDD6B0FEA4DAE67C
|
||||
75E49C839CCD7019D9CE90AC364F488468B2AB01E387A8BEF8815915925166A6
|
||||
CFAA9F4717568C1EC7B96E0D71D260B828A70484E1D9CA7C99A50D10704F8BBBAE62EE98C9FBDFF06F357F1C1E2F2677
|
||||
41E4D250B92BC57442B91DE2015C41226531CF9A8D77B83AFC8E4F3183DB11DE
|
||||
45EA8BD854D7F044FB249C16F08A0C24FF117D54BC20A4CC667B3DAD09EAC4F9
|
||||
F455CA0BB8B496C301406DE4FB52C9B0F64645776803BC2935A2F38675318BE2
|
||||
22FF72A5D2E1A2EBFB6C55FFD0A3CEA0474CCBD13462D63229C9708276E87D3F
|
||||
8470F9A300170F226C0216C07AA829591CBD4CE34AA918EAE49363BDE86CC77EEEBEEA84A097488D35B92F773F5DBB4C
|
||||
IV: 23 17 32 54 92 3A 28 13 12 DE 8B A7 24 71 25 74
|
||||
B8ACA082EA4B34E8B217A6FE63F3545D160AB7F4833C87E8743BAA7002ACC123
|
||||
E779135FE66629CAC4661B1C3D5C9857C9417CAF216241933FF6CE60A74D53C0
|
||||
15340C049A444C79ED489619A31E2AFDCFF6E4864CC4D9B1DA8E98D7EAB9C8D5
|
||||
8E696E85837B3BA8D6D380E1F36E445D630CF0B7B18A45930A08F832EE634A02
|
||||
C85341BE669E509E902FEFCA7D025A20DC80D4F14FE1C3542B1DC3A5C7393A36F901A63C3BC074B058897B12F0F5F0D6
|
||||
2834E5D7726670A03ED6C8B27B5863EEE2FD3668795251AB65B9E4FF76ADEC3E
|
||||
8E71AF7660BCFC545E92674D74F98A35FCF1B54AB5BACCEE182B7F8EDB3FA356
|
||||
C20442D506332D1A410AF3187C29BE01729C282A69B85CF8D92D70FAE3407BA8
|
||||
00BC449D006566A6549A86F52B98410871B0C14D60C181BFC017446B192C934A
|
||||
8A6A28DAF1F61867B1209AB9105986A7383ECE72A40F8D93F1D0066251800A3A
|
||||
4A6AFDFA6130A50180358B111145D7914C720E04D69EE5459C049FCD64249153315F86A5A9F75AEE5CB726847BA64F2A
|
||||
91F838BC515C8CDD32C5803679B81A24FD5CF0C3A4AEA2C07342ACA1020E05F3B393A410B33847A8C48141D923202CF3
|
||||
7C4DEBC03295291EC5B2EBB002670D14E7C972F32DB2B3CD4E61B2BE846345D9
|
||||
8FFEB948DA3D1A7FCF620F043B1D35354F83861F22B6D693F2A7119A2E287D01
|
||||
309C66AF38E6447CB33FB0967C9365CA36314DBF74695F63CF9E558A4FF5193B
|
||||
411D32EC6ADED3360DE9E9A0962F97DF2B80A09F2A2AC8D4DB6DB09FAD6EA217
|
||||
A5E5550BD59425003F9166237CD4BB6A323885D7916F71F3B2795B8A4C7125ACC1237BBF0840F0E999BD2EC14327654F
|
||||
4370A828AFED684B96E8EDAB670C46D2D525FCB7E469B63CD1228C902C3ACF4E
|
||||
88E3853F58129C4D834B18E4D01785591094301148D802A3A21B63521DDDA325
|
||||
D5365BF55DFE7107909684F4ECCE052E617F91FAF08CE5254721A30BEF87F368F329C46439BD1EA2819DC416B2CEF247
|
||||
BDAB9FFD3A82ECE05E8CA00F11954CDB1C124B558A5D369DFE16D32C3AEF08B2013945CC69212F170F17F62A55D35928
|
||||
8E448AA1D39C894F306FE65B0D0DD733717EF81758FFA908AF7583BFD00108E5
|
||||
019A1B0AA3492427DF3DB817B438D0302B0B8C77807D19EE45EAC7F697B2EB85
|
||||
C678A3F9DA726FE1688F86BB063EA017EDB5389E0F185484D9F5DFD4EBEE0579
|
||||
760F77AB9BD99593AC855E4AE00FBAFBB34FA2BFF504BD5CC9557658E850C6D0
|
||||
4F3E77342E9A655D4EC167E2B0428833FEE31CF603FA1CE3D1BCD619D5C9D511
|
||||
2233EFBEDD4A3A95BA8160EFCED533D9F25B65AAB10F627681D2753871814366
|
||||
A1261BE878933B4905956BE7708F7C40E999714503B52B8021D44E131D87FF6C
|
||||
8F31E76314A46EA9B0CCD3EDA4B2DF603829D8E3AF8CE41AEA6BFFBA2E2990AC
|
||||
850C08E45CDA4E42BD4F09B956299C0ED58615BE3664791C88D1E2608D46D205
|
||||
6283656518C6ADFC3B7D309D2763BD91111720CD51029FAA691211DEFF84CB47
|
||||
9FCAF9F77C9D1B9B6934E53DB10DFF88D392D8E7BB4DC28D65F65DC396E2E00A
|
||||
41D2406BE1887FCC094861E4DF0683B1BE534C5CBF059259E946F9D04222C2AB
|
||||
1D6F37E645591F0C491312C1E0CB54F1A6B70F94B54D63100C4584AA016DB589338A704B6D8B6B89C2381F660D987A2F
|
||||
DCEA08D6E5C0D6229EBDE07DBB6CBC0EA8D6E24A3B631CC3775CE23A496CF178
|
||||
907051215A741BE55603F27C3FD86561CC6231CEED83AA76665D6A0B6B3FEC88
|
||||
36CD5B5BCC63D45B89592B2938D6542B9D82AB47BEB73C0D30D2EC19BD8B35C2
|
||||
1FD9651ABAD773D6D22DE677CF7B19615D5B805594DCA117F04AC3255AE8184A
|
||||
4900723A8F7736C9BEAE938EE021F3E44AD806244010F825D04C59E6C67B5EA2
|
||||
0D56A8CE77106DA2CB44F65B8CF5F4A024B9CC774D1C4CB8E862C95BD30B42E7B2E946CAC361F2830361C010DC938833
|
||||
11543FD104EA7D68B6B9C3BFE3F25A84F651FCB7FB5423AADDC472A48E12AFB2
|
||||
98CD236E8B92D706DA0F92F43AC1D2CAF1CFBCDC7B330A7C9D65CDC4F2E2A677
|
||||
753557A9A5075C033206111E3C832044227A32EBF3AB2B08F6FBFCC2109B2F2A
|
||||
4AA124232EF6C25CB7321F5E5F7BE11114C763F8DDAFB6B05E8412ADF37B5C7B
|
||||
01514EA408E26BAFD30290429DE1A0211F4FBDB09DE2E66CE92A6F09B998EF29
|
||||
4715716D5AFF99A2D8205A46AEEF0BC20D72F3F54991F7DF4142FF187485C178
|
||||
281A32B90F8B85F31F54BF0D83B6D03E4E65A72ADB3D5A297C91881E36B45E8F
|
||||
9C05D3CB9F473D5693697A8567DBA7CF650C0A0D6C1BBE3ACE78ACDE0BD027B6C836B6CB6365D5B5D00F101FA83876B9
|
||||
DC88B0237634CB007244A4169A5D9F5F65FC782E3C4388358A7E2019F7B4CC05
|
||||
BC7ACAA91D23616A0070DCA328901DDDE3BB5B59260FB45083916B6ED0E6450C
|
||||
A280434D059D652D77ACB9F44409CDC7393A876239BA894DD4BE843FAB0AC561
|
||||
334F1316A35EB8A838F6B209FA4F8148062972E27A296379731B1F728A0BB32E
|
||||
DDC9883E90EBE73915CFDF8EA7193F2449B66010D45F5EC6F20949D5C49719A9298B95269531A3440577B00EADE1B379
|
||||
|
||||
@ -24,10 +24,10 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
// Device Info version
|
||||
if(sep == '.') {
|
||||
property_value_out(&property_context, NULL, 2, "format", "major", "3");
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "2");
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "3");
|
||||
} else {
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "major", "2");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "3");
|
||||
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "4");
|
||||
}
|
||||
|
||||
// Model name
|
||||
@ -298,6 +298,7 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
property_value_out(&property_context, NULL, 2, "radio", "alive", "false");
|
||||
}
|
||||
|
||||
// RTC flags
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
@ -305,8 +306,52 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
|
||||
"system",
|
||||
"debug",
|
||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug));
|
||||
property_value_out(
|
||||
&property_context, "%u", 2, "system", "lock", furi_hal_rtc_is_flag_set(FuriHalRtcFlagLock));
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
2,
|
||||
"system",
|
||||
"orient",
|
||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient));
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
3,
|
||||
"system",
|
||||
"sleep",
|
||||
"legacy",
|
||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagLegacySleep));
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
2,
|
||||
"system",
|
||||
"stealth",
|
||||
furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode));
|
||||
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "system", "heap", "track", furi_hal_rtc_get_heap_track_mode());
|
||||
property_value_out(&property_context, "%u", 2, "system", "boot", furi_hal_rtc_get_boot_mode());
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
3,
|
||||
"system",
|
||||
"locale",
|
||||
"time",
|
||||
furi_hal_rtc_get_locale_timeformat());
|
||||
property_value_out(
|
||||
&property_context,
|
||||
"%u",
|
||||
3,
|
||||
"system",
|
||||
"locale",
|
||||
"date",
|
||||
furi_hal_rtc_get_locale_dateformat());
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "system", "locale", "unit", furi_hal_rtc_get_locale_units());
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "system", "log", "level", furi_hal_rtc_get_log_level());
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ typedef enum {
|
||||
FuriHalVersionColorUnknown = 0x00,
|
||||
FuriHalVersionColorBlack = 0x01,
|
||||
FuriHalVersionColorWhite = 0x02,
|
||||
FuriHalVersionColorTransparent = 0x03,
|
||||
} FuriHalVersionColor;
|
||||
|
||||
/** Device Regions */
|
||||
|
||||
@ -28,7 +28,7 @@ typedef enum {
|
||||
FuriThreadPriorityNormal = 16, /**< Normal */
|
||||
FuriThreadPriorityHigh = 17, /**< High */
|
||||
FuriThreadPriorityHighest = 18, /**< Highest */
|
||||
FuriThreadPriorityIsr = 32, /**< Deffered Isr (highest possible) */
|
||||
FuriThreadPriorityIsr = (configMAX_PRIORITIES - 1), /**< Deferred ISR (highest possible) */
|
||||
} FuriThreadPriority;
|
||||
|
||||
/** FuriThread anonymous structure */
|
||||
|
||||
@ -157,14 +157,6 @@ static bool flipper_application_assets_process_dirs(
|
||||
FuriString* full_path = flipper_application_assets_alloc_app_full_path(app_name);
|
||||
|
||||
do {
|
||||
if(!storage_simply_mkdir(storage, APPS_ASSETS_PATH)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!storage_simply_mkdir(storage, furi_string_get_cstr(full_path))) {
|
||||
break;
|
||||
}
|
||||
|
||||
FuriString* dir_path = furi_string_alloc();
|
||||
char* path = NULL;
|
||||
|
||||
@ -279,6 +271,8 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
|
||||
|
||||
FURI_LOG_D(TAG, "Loading assets for %s", furi_string_get_cstr(app_name));
|
||||
|
||||
FuriString* full_path = flipper_application_assets_alloc_app_full_path(app_name);
|
||||
|
||||
do {
|
||||
if(!storage_file_seek(file, offset, true)) {
|
||||
break;
|
||||
@ -319,13 +313,23 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
|
||||
FURI_LOG_D(TAG, "Assets removed");
|
||||
}
|
||||
|
||||
if(!storage_simply_mkdir(storage, APPS_ASSETS_PATH)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!storage_simply_mkdir(storage, furi_string_get_cstr(full_path))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// process directories
|
||||
if(!flipper_application_assets_process_dirs(storage, file, app_name, header.dirs_count)) {
|
||||
if(header.dirs_count &&
|
||||
!flipper_application_assets_process_dirs(storage, file, app_name, header.dirs_count)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// process files
|
||||
if(!flipper_application_assets_process_files(storage, file, app_name, header.files_count)) {
|
||||
if(header.files_count && !flipper_application_assets_process_files(
|
||||
storage, file, app_name, header.files_count)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -353,6 +357,7 @@ bool flipper_application_assets_load(File* file, const char* elf_path, size_t of
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
furi_string_free(full_path);
|
||||
furi_string_free(app_name);
|
||||
|
||||
FURI_LOG_D(TAG, "Assets loading %s", result ? "success" : "failed");
|
||||
|
||||
@ -810,16 +810,10 @@ static void nfc_worker_mf_classic_key_attack(
|
||||
uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying A key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
FURI_LOG_D(TAG, "Trying A key for sector %d, key: %012llX", i, key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
||||
FURI_LOG_D(
|
||||
TAG, "Key A found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key);
|
||||
FURI_LOG_D(TAG, "Key A found: %012llX", key);
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
||||
|
||||
uint64_t found_key;
|
||||
@ -832,18 +826,13 @@ static void nfc_worker_mf_classic_key_attack(
|
||||
}
|
||||
}
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
}
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Trying B key for sector %d, key: %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
FURI_LOG_D(TAG, "Trying B key for sector %d, key: %012llX", i, key);
|
||||
if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
||||
FURI_LOG_D(
|
||||
TAG, "Key B found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key);
|
||||
FURI_LOG_D(TAG, "Key B found: %012llX", key);
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
||||
}
|
||||
}
|
||||
@ -891,8 +880,9 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context);
|
||||
uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i);
|
||||
if(mf_classic_is_sector_read(data, i)) continue;
|
||||
bool is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA);
|
||||
bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
||||
if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
|
||||
mf_classic_is_key_found(data, i, MfClassicKeyB))
|
||||
continue;
|
||||
uint16_t key_index = 0;
|
||||
while(mf_classic_dict_get_next_key(dict, &key)) {
|
||||
FURI_LOG_T(TAG, "Key %d", key_index);
|
||||
@ -910,19 +900,12 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
nfc_worker_mf_classic_key_attack(nfc_worker, prev_key, &tx_rx, i);
|
||||
deactivated = true;
|
||||
}
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"Try to auth to sector %d with key %04lx%08lx",
|
||||
i,
|
||||
(uint32_t)(key >> 32),
|
||||
(uint32_t)key);
|
||||
if(!is_key_a_found) {
|
||||
is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA);
|
||||
FURI_LOG_D(TAG, "Try to auth to sector %d with key %012llX", i, key);
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) {
|
||||
if(mf_classic_authenticate_skip_activate(
|
||||
&tx_rx, block_num, key, MfClassicKeyA, !deactivated, cuid)) {
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyA, key);
|
||||
FURI_LOG_D(
|
||||
TAG, "Key A found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key);
|
||||
FURI_LOG_D(TAG, "Key A found: %012llX", key);
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context);
|
||||
|
||||
uint64_t found_key;
|
||||
@ -952,22 +935,24 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
|
||||
if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
|
||||
memcmp(sec_trailer->key_a, current_key, 6) == 0) {
|
||||
mf_classic_set_key_not_found(data, i, MfClassicKeyA);
|
||||
is_key_a_found = false;
|
||||
FURI_LOG_D(TAG, "Key %dA not found in attack", i);
|
||||
if(!mf_classic_authenticate_skip_activate(
|
||||
&tx_rx, block_num, key, MfClassicKeyA, !deactivated, cuid)) {
|
||||
mf_classic_set_key_not_found(data, i, MfClassicKeyA);
|
||||
FURI_LOG_D(TAG, "Key %dA not found in attack", i);
|
||||
}
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
deactivated = true;
|
||||
}
|
||||
if(!is_key_b_found) {
|
||||
is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB);
|
||||
if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) {
|
||||
if(mf_classic_authenticate_skip_activate(
|
||||
&tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) {
|
||||
FURI_LOG_D(
|
||||
TAG, "Key B found: %04lx%08lx", (uint32_t)(key >> 32), (uint32_t)key);
|
||||
&tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) { //-V547
|
||||
FURI_LOG_D(TAG, "Key B found: %012llX", key);
|
||||
mf_classic_set_key_found(data, i, MfClassicKeyB, key);
|
||||
nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context);
|
||||
nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1);
|
||||
}
|
||||
deactivated = true;
|
||||
deactivated = true; //-V1048
|
||||
} else {
|
||||
// If the key B is marked as found and matches the searching key, invalidate it
|
||||
MfClassicSectorTrailer* sec_trailer =
|
||||
@ -978,12 +963,18 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) {
|
||||
|
||||
if(mf_classic_is_key_found(data, i, MfClassicKeyB) &&
|
||||
memcmp(sec_trailer->key_b, current_key, 6) == 0) {
|
||||
mf_classic_set_key_not_found(data, i, MfClassicKeyB);
|
||||
is_key_b_found = false;
|
||||
FURI_LOG_D(TAG, "Key %dB not found in attack", i);
|
||||
if(!mf_classic_authenticate_skip_activate(
|
||||
&tx_rx, block_num, key, MfClassicKeyB, !deactivated, cuid)) { //-V547
|
||||
mf_classic_set_key_not_found(data, i, MfClassicKeyB);
|
||||
FURI_LOG_D(TAG, "Key %dB not found in attack", i);
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
deactivated = true; //-V1048
|
||||
}
|
||||
}
|
||||
if(is_key_a_found && is_key_b_found) break;
|
||||
if(mf_classic_is_key_found(data, i, MfClassicKeyA) &&
|
||||
mf_classic_is_key_found(data, i, MfClassicKeyB))
|
||||
break;
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break;
|
||||
} else {
|
||||
if(!card_removed_notified) {
|
||||
|
||||
@ -467,6 +467,19 @@ static inline bool subghz_protocol_keeloq_check_decrypt(
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Centurion specific check
|
||||
static inline bool subghz_protocol_keeloq_check_decrypt_centurion(
|
||||
SubGhzBlockGeneric* instance,
|
||||
uint32_t decrypt,
|
||||
uint8_t btn) {
|
||||
furi_assert(instance);
|
||||
|
||||
if((decrypt >> 28 == btn) && (((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0x1CE))) {
|
||||
instance->cnt = decrypt & 0x0000FFFF;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking the accepted code against the database manafacture key
|
||||
@ -509,9 +522,16 @@ static uint8_t subghz_protocol_keeloq_check_remote_controller_selector(
|
||||
// https://phreakerclub.com/forum/showpost.php?p=43557&postcount=37
|
||||
man = subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key);
|
||||
decrypt = subghz_protocol_keeloq_common_decrypt(hop, man);
|
||||
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
return 1;
|
||||
if((strcmp(furi_string_get_cstr(manufacture_code->name), "Centurion") == 0)) {
|
||||
if(subghz_protocol_keeloq_check_decrypt_centurion(instance, decrypt, btn)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if(subghz_protocol_keeloq_check_decrypt(instance, decrypt, btn, end_serial)) {
|
||||
*manufacture_name = furi_string_get_cstr(manufacture_code->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KEELOQ_LEARNING_SECURE:
|
||||
|
||||
@ -17,6 +17,7 @@ OTP_COLORS = {
|
||||
"unknown": 0x00,
|
||||
"black": 0x01,
|
||||
"white": 0x02,
|
||||
"transparent": 0x03,
|
||||
}
|
||||
|
||||
OTP_REGIONS = {
|
||||
|
||||
@ -38,11 +38,11 @@ fbtenv_wget()
|
||||
fbtenv_restore_env()
|
||||
{
|
||||
TOOLCHAIN_ARCH_DIR_SED="$(echo "$TOOLCHAIN_ARCH_DIR" | sed 's/\//\\\//g')"
|
||||
PATH="$(echo "$PATH" | /usr/bin/sed "s/$TOOLCHAIN_ARCH_DIR_SED\/python\/bin://g")";
|
||||
PATH="$(echo "$PATH" | /usr/bin/sed "s/$TOOLCHAIN_ARCH_DIR_SED\/bin://g")";
|
||||
PATH="$(echo "$PATH" | /usr/bin/sed "s/$TOOLCHAIN_ARCH_DIR_SED\/protobuf\/bin://g")";
|
||||
PATH="$(echo "$PATH" | /usr/bin/sed "s/$TOOLCHAIN_ARCH_DIR_SED\/openocd\/bin://g")";
|
||||
PATH="$(echo "$PATH" | /usr/bin/sed "s/$TOOLCHAIN_ARCH_DIR_SED\/openssl\/bin://g")";
|
||||
PATH="$(echo "$PATH" | sed "s/$TOOLCHAIN_ARCH_DIR_SED\/python\/bin://g")";
|
||||
PATH="$(echo "$PATH" | sed "s/$TOOLCHAIN_ARCH_DIR_SED\/bin://g")";
|
||||
PATH="$(echo "$PATH" | sed "s/$TOOLCHAIN_ARCH_DIR_SED\/protobuf\/bin://g")";
|
||||
PATH="$(echo "$PATH" | sed "s/$TOOLCHAIN_ARCH_DIR_SED\/openocd\/bin://g")";
|
||||
PATH="$(echo "$PATH" | sed "s/$TOOLCHAIN_ARCH_DIR_SED\/openssl\/bin://g")";
|
||||
if [ -n "${PS1:-""}" ]; then
|
||||
PS1="$(echo "$PS1" | sed 's/\[fbt\]//g')";
|
||||
elif [ -n "${PROMPT:-""}" ]; then
|
||||
@ -82,6 +82,9 @@ fbtenv_restore_env()
|
||||
|
||||
fbtenv_check_sourced()
|
||||
{
|
||||
if [ -n "${FBT_SKIP_CHECK_SOURCED:-""}" ]; then
|
||||
return 0;
|
||||
fi
|
||||
case "${ZSH_EVAL_CONTEXT:-""}" in *:file:*)
|
||||
setopt +o nomatch; # disabling 'no match found' warning in zsh
|
||||
return 0;;
|
||||
@ -104,8 +107,6 @@ fbtenv_check_if_sourced_multiple_times()
|
||||
return 0;
|
||||
fi
|
||||
fi
|
||||
echo "Warning! FBT environment script was sourced more than once!";
|
||||
echo "You might be doing things wrong, please open a new shell!";
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -160,7 +161,7 @@ fbtenv_get_kernel_type()
|
||||
fbtenv_check_rosetta()
|
||||
{
|
||||
if [ "$ARCH_TYPE" = "arm64" ]; then
|
||||
if ! /usr/bin/pgrep -q oahd; then
|
||||
if ! pgrep -q oahd; then
|
||||
echo "Flipper Zero Toolchain needs Rosetta2 to run under Apple Silicon";
|
||||
echo "Please instal it by typing 'softwareupdate --install-rosetta --agree-to-license'";
|
||||
return 1;
|
||||
@ -202,7 +203,7 @@ fbtenv_download_toolchain_tar()
|
||||
return 0;
|
||||
}
|
||||
|
||||
fbtenv_remove_old_tooclhain()
|
||||
fbtenv_remove_old_toolchain()
|
||||
{
|
||||
printf "Removing old toolchain..";
|
||||
rm -rf "${TOOLCHAIN_ARCH_DIR:?}";
|
||||
@ -233,12 +234,14 @@ fbtenv_unpack_toolchain()
|
||||
|
||||
fbtenv_cleanup()
|
||||
{
|
||||
printf "Cleaning up..";
|
||||
if [ -n "${FBT_TOOLCHAIN_PATH:-""}" ]; then
|
||||
rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/"*.tar.gz;
|
||||
printf "Cleaning up..";
|
||||
rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/"*.part;
|
||||
if [ -z "${FBT_PRESERVE_TAR:-""}" ]; then
|
||||
rm -rf "${FBT_TOOLCHAIN_PATH:?}/toolchain/"*.tar.gz;
|
||||
fi
|
||||
echo "done";
|
||||
fi
|
||||
echo "done";
|
||||
trap - 2;
|
||||
return 0;
|
||||
}
|
||||
@ -291,16 +294,22 @@ fbtenv_download_toolchain()
|
||||
fbtenv_curl_wget_check || return 1;
|
||||
fbtenv_download_toolchain_tar || return 1;
|
||||
fi
|
||||
fbtenv_remove_old_tooclhain;
|
||||
fbtenv_remove_old_toolchain;
|
||||
fbtenv_unpack_toolchain || return 1;
|
||||
fbtenv_cleanup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fbtenv_print_version()
|
||||
fbtenv_print_config()
|
||||
{
|
||||
if [ -n "$FBT_VERBOSE" ]; then
|
||||
if [ -n "${FBT_VERBOSE:-""}" ]; then
|
||||
echo "FBT: using toolchain version $(cat "$TOOLCHAIN_ARCH_DIR/VERSION")";
|
||||
if [ -n "${FBT_SKIP_CHECK_SOURCED:-""}" ]; then
|
||||
echo "FBT: fbtenv will not check if it is sourced or not";
|
||||
fi
|
||||
if [ -n "${FBT_PRESERVE_TAR:-""}" ]; then
|
||||
echo "FBT: toolchain archives will be saved";
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@ -312,11 +321,13 @@ fbtenv_main()
|
||||
fbtenv_restore_env;
|
||||
return 0;
|
||||
fi
|
||||
fbtenv_check_if_sourced_multiple_times;
|
||||
if ! fbtenv_check_if_sourced_multiple_times; then
|
||||
return 0;
|
||||
fi;
|
||||
fbtenv_check_env_vars || return 1;
|
||||
fbtenv_check_download_toolchain || return 1;
|
||||
fbtenv_set_shell_prompt;
|
||||
fbtenv_print_version;
|
||||
fbtenv_print_config;
|
||||
PATH="$TOOLCHAIN_ARCH_DIR/python/bin:$PATH";
|
||||
PATH="$TOOLCHAIN_ARCH_DIR/bin:$PATH";
|
||||
PATH="$TOOLCHAIN_ARCH_DIR/protobuf/bin:$PATH";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user