Merge remote-tracking branch 'origin/dev' into release-candidate

This commit is contained in:
Aleksandr Kutuzov 2023-08-03 16:29:04 +09:00
commit 45e78fbdc2
32 changed files with 788 additions and 350 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View 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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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"

View File

@ -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
};

View File

@ -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);

View File

@ -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;

View File

@ -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 =

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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());

View File

@ -33,6 +33,7 @@ typedef enum {
FuriHalVersionColorUnknown = 0x00,
FuriHalVersionColorBlack = 0x01,
FuriHalVersionColorWhite = 0x02,
FuriHalVersionColorTransparent = 0x03,
} FuriHalVersionColor;
/** Device Regions */

View File

@ -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 */

View File

@ -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");

View File

@ -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) {

View File

@ -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:

View File

@ -17,6 +17,7 @@ OTP_COLORS = {
"unknown": 0x00,
"black": 0x01,
"white": 0x02,
"transparent": 0x03,
}
OTP_REGIONS = {

View File

@ -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";