mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
Merge branch 'dev' of https://github.com/flipperdevices/flipperzero-firmware into mntm-dev
This commit is contained in:
@@ -12,7 +12,7 @@ void subghz_test_scene_show_only_rx_on_enter(void* context) {
|
||||
// Setup view
|
||||
Popup* popup = app->popup;
|
||||
|
||||
const char* header_text = "Transmission is blocked";
|
||||
const char* header_text = "Transmission is Blocked";
|
||||
const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region";
|
||||
if(!furi_hal_region_is_provisioned()) {
|
||||
header_text = "Firmware update needed";
|
||||
|
||||
Submodule applications/external updated: 011d43030c...8fc8f9a6bd
@@ -345,9 +345,9 @@ BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
BadKbAppViewVarItemList,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
app->bad_kb_view = bad_kb_alloc();
|
||||
app->bad_kb_view = bad_kb_view_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadKbAppViewWork, bad_kb_get_view(app->bad_kb_view));
|
||||
app->view_dispatcher, BadKbAppViewWork, bad_kb_view_get_view(app->bad_kb_view));
|
||||
|
||||
app->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
@@ -389,7 +389,7 @@ void bad_kb_app_free(BadKbApp* app) {
|
||||
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadKbAppViewWork);
|
||||
bad_kb_free(app->bad_kb_view);
|
||||
bad_kb_view_free(app->bad_kb_view);
|
||||
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadKbAppViewWidget);
|
||||
|
||||
@@ -173,6 +173,49 @@ static int32_t ducky_fnc_release(BadKbScript* bad_kb, const char* line, int32_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_media(BadKbScript* bad_kb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[ducky_get_command_len(line) + 1];
|
||||
uint16_t key = ducky_get_media_keycode_by_name(line);
|
||||
if(key == HID_CONSUMER_UNASSIGNED) {
|
||||
return ducky_error(bad_kb, "No keycode defined for %s", line);
|
||||
}
|
||||
if(bad_kb->bt) {
|
||||
ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
|
||||
furi_delay_ms(bt_timeout);
|
||||
ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
|
||||
} else {
|
||||
furi_hal_hid_kb_press(key);
|
||||
furi_hal_hid_kb_release(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_globe(BadKbScript* bad_kb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
|
||||
line = &line[ducky_get_command_len(line) + 1];
|
||||
uint16_t key = ducky_get_keycode(bad_kb, line, true);
|
||||
if(key == HID_KEYBOARD_NONE) {
|
||||
return ducky_error(bad_kb, "No keycode defined for %s", line);
|
||||
}
|
||||
|
||||
if(bad_kb->bt) {
|
||||
ble_profile_hid_consumer_key_press(bad_kb->app->ble_hid, HID_CONSUMER_FN_GLOBE);
|
||||
ble_profile_hid_kb_press(bad_kb->app->ble_hid, key);
|
||||
furi_delay_ms(bt_timeout);
|
||||
ble_profile_hid_kb_release(bad_kb->app->ble_hid, key);
|
||||
ble_profile_hid_consumer_key_release(bad_kb->app->ble_hid, HID_CONSUMER_FN_GLOBE);
|
||||
} else {
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_FN_GLOBE);
|
||||
furi_hal_hid_kb_press(key);
|
||||
furi_hal_hid_kb_release(key);
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_FN_GLOBE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t ducky_fnc_waitforbutton(BadKbScript* bad_kb, const char* line, int32_t param) {
|
||||
UNUSED(param);
|
||||
UNUSED(bad_kb);
|
||||
@@ -202,6 +245,8 @@ static const DuckyCmd ducky_commands[] = {
|
||||
{"HOLD", ducky_fnc_hold, -1},
|
||||
{"RELEASE", ducky_fnc_release, -1},
|
||||
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
|
||||
{"MEDIA", ducky_fnc_media, -1},
|
||||
{"GLOBE", ducky_fnc_globe, -1},
|
||||
};
|
||||
|
||||
#define TAG "BadKb"
|
||||
|
||||
@@ -53,6 +53,8 @@ bool ducky_is_line_end(const char chr);
|
||||
|
||||
uint16_t ducky_get_keycode_by_name(const char* param);
|
||||
|
||||
uint16_t ducky_get_media_keycode_by_name(const char* param);
|
||||
|
||||
bool ducky_get_number(const char* param, uint32_t* val);
|
||||
|
||||
void ducky_numlock_on(BadKbScript* bad_kb);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include "ducky_script_i.h"
|
||||
|
||||
typedef struct {
|
||||
@@ -78,6 +77,37 @@ static const DuckyKey ducky_keys[] = {
|
||||
{"F24", HID_KEYBOARD_F24},
|
||||
};
|
||||
|
||||
static const DuckyKey ducky_media_keys[] = {
|
||||
{"POWER", HID_CONSUMER_POWER},
|
||||
{"REBOOT", HID_CONSUMER_RESET},
|
||||
{"SLEEP", HID_CONSUMER_SLEEP},
|
||||
{"LOGOFF", HID_CONSUMER_AL_LOGOFF},
|
||||
|
||||
{"EXIT", HID_CONSUMER_AC_EXIT},
|
||||
{"HOME", HID_CONSUMER_AC_HOME},
|
||||
{"BACK", HID_CONSUMER_AC_BACK},
|
||||
{"FORWARD", HID_CONSUMER_AC_FORWARD},
|
||||
{"REFRESH", HID_CONSUMER_AC_REFRESH},
|
||||
|
||||
{"SNAPSHOT", HID_CONSUMER_SNAPSHOT},
|
||||
|
||||
{"PLAY", HID_CONSUMER_PLAY},
|
||||
{"PAUSE", HID_CONSUMER_PAUSE},
|
||||
{"PLAY_PAUSE", HID_CONSUMER_PLAY_PAUSE},
|
||||
{"NEXT_TRACK", HID_CONSUMER_SCAN_NEXT_TRACK},
|
||||
{"PREV_TRACK", HID_CONSUMER_SCAN_PREVIOUS_TRACK},
|
||||
{"STOP", HID_CONSUMER_STOP},
|
||||
{"EJECT", HID_CONSUMER_EJECT},
|
||||
|
||||
{"MUTE", HID_CONSUMER_MUTE},
|
||||
{"VOLUME_UP", HID_CONSUMER_VOLUME_INCREMENT},
|
||||
{"VOLUME_DOWN", HID_CONSUMER_VOLUME_DECREMENT},
|
||||
|
||||
{"FN", HID_CONSUMER_FN_GLOBE},
|
||||
{"BRIGHT_UP", HID_CONSUMER_BRIGHTNESS_INCREMENT},
|
||||
{"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT},
|
||||
};
|
||||
|
||||
uint16_t ducky_get_keycode_by_name(const char* param) {
|
||||
for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) {
|
||||
size_t key_cmd_len = strlen(ducky_keys[i].name);
|
||||
@@ -89,3 +119,15 @@ uint16_t ducky_get_keycode_by_name(const char* param) {
|
||||
|
||||
return HID_KEYBOARD_NONE;
|
||||
}
|
||||
|
||||
uint16_t ducky_get_media_keycode_by_name(const char* param) {
|
||||
for(size_t i = 0; i < COUNT_OF(ducky_media_keys); i++) {
|
||||
size_t key_cmd_len = strlen(ducky_media_keys[i].name);
|
||||
if((strncmp(param, ducky_media_keys[i].name, key_cmd_len) == 0) &&
|
||||
(ducky_is_line_end(param[key_cmd_len]))) {
|
||||
return ducky_media_keys[i].keycode;
|
||||
}
|
||||
}
|
||||
|
||||
return HID_CONSUMER_UNASSIGNED;
|
||||
}
|
||||
|
||||
80
applications/main/bad_kb/resources/badusb/demo_chromeos.txt
Normal file
80
applications/main/bad_kb/resources/badusb/demo_chromeos.txt
Normal file
@@ -0,0 +1,80 @@
|
||||
REM This is BadUSB demo script for ChromeOS by kowalski7cc
|
||||
|
||||
REM Open a new tab
|
||||
CTRL t
|
||||
REM wait for some slower chromebooks
|
||||
DELAY 1000
|
||||
REM Open an empty editable page
|
||||
DEFAULT_DELAY 50
|
||||
STRING data:text/html, <html contenteditable autofocus><style>body{font-family:monospace;}
|
||||
ENTER
|
||||
DELAY 500
|
||||
|
||||
STRING Hello World!
|
||||
ENTER
|
||||
|
||||
REM Copy-Paste previous string
|
||||
UP
|
||||
HOME
|
||||
SHIFT DOWN
|
||||
CTRL c
|
||||
RIGHT
|
||||
CTRL v
|
||||
CTRL v
|
||||
|
||||
|
||||
STRING =
|
||||
REPEAT 59
|
||||
ENTER
|
||||
ENTER
|
||||
|
||||
STRING _.-------.._ -,
|
||||
ENTER
|
||||
HOME
|
||||
STRING .-"```"--..,,_/ /`-, -, \
|
||||
ENTER
|
||||
HOME
|
||||
STRING .:" /:/ /'\ \ ,_..., `. | |
|
||||
ENTER
|
||||
HOME
|
||||
STRING / ,----/:/ /`\ _\~`_-"` _;
|
||||
ENTER
|
||||
HOME
|
||||
STRING ' / /`"""'\ \ \.~`_-' ,-"'/
|
||||
ENTER
|
||||
HOME
|
||||
STRING | | | 0 | | .-' ,/` /
|
||||
ENTER
|
||||
HOME
|
||||
STRING | ,..\ \ ,.-"` ,/` /
|
||||
ENTER
|
||||
HOME
|
||||
STRING ; : `/`""\` ,/--==,/-----,
|
||||
ENTER
|
||||
HOME
|
||||
STRING | `-...| -.___-Z:_______J...---;
|
||||
ENTER
|
||||
HOME
|
||||
STRING : ` _-'
|
||||
ENTER
|
||||
HOME
|
||||
STRING _L_ _ ___ ___ ___ ___ ____--"`
|
||||
ENTER
|
||||
HOME
|
||||
STRING | __|| | |_ _|| _ \| _ \| __|| _ \
|
||||
ENTER
|
||||
HOME
|
||||
STRING | _| | |__ | | | _/| _/| _| | /
|
||||
ENTER
|
||||
HOME
|
||||
STRING |_| |____||___||_| |_| |___||_|_\
|
||||
ENTER
|
||||
HOME
|
||||
ENTER
|
||||
|
||||
STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script format
|
||||
ENTER
|
||||
STRING More information about script syntax can be found here:
|
||||
ENTER
|
||||
STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md
|
||||
ENTER
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../bad_kb_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
|
||||
enum VarItemListIndex {
|
||||
VarItemListIndexKeyboardLayout,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../bad_kb_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
static bool bad_kb_layout_select(BadKbApp* bad_kb) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../bad_kb_app_i.h"
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
static bool bad_kb_file_select(BadKbApp* bad_kb) {
|
||||
|
||||
@@ -16,7 +16,7 @@ bool bad_kb_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InputKeyLeft) {
|
||||
if(bad_kb_is_idle_state(app->bad_kb_view)) {
|
||||
if(bad_kb_view_is_idle_state(app->bad_kb_view)) {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfig);
|
||||
}
|
||||
consumed = true;
|
||||
@@ -28,7 +28,7 @@ bool bad_kb_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
bad_kb_set_state(app->bad_kb_view, bad_kb_script_get_state(app->bad_kb_script));
|
||||
bad_kb_view_set_state(app->bad_kb_view, bad_kb_script_get_state(app->bad_kb_script));
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
@@ -39,18 +39,18 @@ void bad_kb_scene_work_on_enter(void* context) {
|
||||
FuriString* file_name;
|
||||
file_name = furi_string_alloc();
|
||||
path_extract_filename(app->file_path, file_name, true);
|
||||
bad_kb_set_file_name(app->bad_kb_view, furi_string_get_cstr(file_name));
|
||||
bad_kb_view_set_file_name(app->bad_kb_view, furi_string_get_cstr(file_name));
|
||||
furi_string_free(file_name);
|
||||
|
||||
FuriString* layout;
|
||||
layout = furi_string_alloc();
|
||||
path_extract_filename(app->keyboard_layout, layout, true);
|
||||
bad_kb_set_layout(app->bad_kb_view, furi_string_get_cstr(layout));
|
||||
bad_kb_view_set_layout(app->bad_kb_view, furi_string_get_cstr(layout));
|
||||
furi_string_free(layout);
|
||||
|
||||
bad_kb_set_state(app->bad_kb_view, bad_kb_script_get_state(app->bad_kb_script));
|
||||
bad_kb_view_set_state(app->bad_kb_view, bad_kb_script_get_state(app->bad_kb_script));
|
||||
|
||||
bad_kb_set_button_callback(app->bad_kb_view, bad_kb_scene_work_button_callback, app);
|
||||
bad_kb_view_set_button_callback(app->bad_kb_view, bad_kb_scene_work_button_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BadKbAppViewWork);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ static void bad_kb_draw_callback(Canvas* canvas, void* _model) {
|
||||
if(state == BadKbStateNotConnected) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect to");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "a device");
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to device");
|
||||
} else if(state == BadKbStateWillRun) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
@@ -211,7 +211,7 @@ static bool bad_kb_input_callback(InputEvent* event, void* context) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
BadKb* bad_kb_alloc(void) {
|
||||
BadKb* bad_kb_view_alloc(void) {
|
||||
BadKb* bad_kb = malloc(sizeof(BadKb));
|
||||
|
||||
bad_kb->view = view_alloc();
|
||||
@@ -223,18 +223,18 @@ BadKb* bad_kb_alloc(void) {
|
||||
return bad_kb;
|
||||
}
|
||||
|
||||
void bad_kb_free(BadKb* bad_kb) {
|
||||
void bad_kb_view_free(BadKb* bad_kb) {
|
||||
furi_assert(bad_kb);
|
||||
view_free(bad_kb->view);
|
||||
free(bad_kb);
|
||||
}
|
||||
|
||||
View* bad_kb_get_view(BadKb* bad_kb) {
|
||||
View* bad_kb_view_get_view(BadKb* bad_kb) {
|
||||
furi_assert(bad_kb);
|
||||
return bad_kb->view;
|
||||
}
|
||||
|
||||
void bad_kb_set_button_callback(BadKb* bad_kb, BadKbButtonCallback callback, void* context) {
|
||||
void bad_kb_view_set_button_callback(BadKb* bad_kb, BadKbButtonCallback callback, void* context) {
|
||||
furi_assert(bad_kb);
|
||||
furi_assert(callback);
|
||||
with_view_model(
|
||||
@@ -248,19 +248,19 @@ void bad_kb_set_button_callback(BadKb* bad_kb, BadKbButtonCallback callback, voi
|
||||
true);
|
||||
}
|
||||
|
||||
void bad_kb_set_file_name(BadKb* bad_kb, const char* name) {
|
||||
void bad_kb_view_set_file_name(BadKb* bad_kb, const char* name) {
|
||||
furi_assert(name);
|
||||
with_view_model(
|
||||
bad_kb->view, BadKbModel * model, { strlcpy(model->file_name, name, MAX_NAME_LEN); }, true);
|
||||
}
|
||||
|
||||
void bad_kb_set_layout(BadKb* bad_kb, const char* layout) {
|
||||
void bad_kb_view_set_layout(BadKb* bad_kb, const char* layout) {
|
||||
furi_assert(layout);
|
||||
with_view_model(
|
||||
bad_kb->view, BadKbModel * model, { strlcpy(model->layout, layout, MAX_NAME_LEN); }, true);
|
||||
}
|
||||
|
||||
void bad_kb_set_state(BadKb* bad_kb, BadKbState* st) {
|
||||
void bad_kb_view_set_state(BadKb* bad_kb, BadKbState* st) {
|
||||
furi_assert(st);
|
||||
uint32_t pin = 0;
|
||||
if(bad_kb->context != NULL) {
|
||||
@@ -283,7 +283,7 @@ void bad_kb_set_state(BadKb* bad_kb, BadKbState* st) {
|
||||
true);
|
||||
}
|
||||
|
||||
bool bad_kb_is_idle_state(BadKb* bad_kb) {
|
||||
bool bad_kb_view_is_idle_state(BadKb* bad_kb) {
|
||||
bool is_idle = false;
|
||||
with_view_model(
|
||||
bad_kb->view,
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
typedef struct BadKb BadKb;
|
||||
typedef void (*BadKbButtonCallback)(InputKey key, void* context);
|
||||
|
||||
BadKb* bad_kb_alloc(void);
|
||||
BadKb* bad_kb_view_alloc(void);
|
||||
|
||||
void bad_kb_free(BadKb* bad_kb);
|
||||
void bad_kb_view_free(BadKb* bad_kb);
|
||||
|
||||
View* bad_kb_get_view(BadKb* bad_kb);
|
||||
View* bad_kb_view_get_view(BadKb* bad_kb);
|
||||
|
||||
void bad_kb_set_button_callback(BadKb* bad_kb, BadKbButtonCallback callback, void* context);
|
||||
void bad_kb_view_set_button_callback(BadKb* bad_kb, BadKbButtonCallback callback, void* context);
|
||||
|
||||
void bad_kb_set_file_name(BadKb* bad_kb, const char* name);
|
||||
void bad_kb_view_set_file_name(BadKb* bad_kb, const char* name);
|
||||
|
||||
void bad_kb_set_layout(BadKb* bad_kb, const char* layout);
|
||||
void bad_kb_view_set_layout(BadKb* bad_kb, const char* layout);
|
||||
|
||||
void bad_kb_set_state(BadKb* bad_kb, BadKbState* st);
|
||||
void bad_kb_view_set_state(BadKb* bad_kb, BadKbState* st);
|
||||
|
||||
bool bad_kb_is_idle_state(BadKb* bad_kb);
|
||||
bool bad_kb_view_is_idle_state(BadKb* bad_kb);
|
||||
|
||||
@@ -6,7 +6,7 @@ void gpio_scene_usb_uart_close_rpc_on_enter(void* context) {
|
||||
|
||||
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
|
||||
widget_add_string_multiline_element(
|
||||
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nis active!");
|
||||
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Connection\nIs Active!");
|
||||
widget_add_string_multiline_element(
|
||||
app->widget,
|
||||
3,
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "infrared_app_i.h"
|
||||
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <toolbox/path.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "InfraredApp"
|
||||
@@ -9,6 +12,13 @@
|
||||
#define INFRARED_TX_MIN_INTERVAL_MS (50U)
|
||||
#define INFRARED_TASK_STACK_SIZE (2048UL)
|
||||
|
||||
#define INFRARED_SETTINGS_VERSION (0)
|
||||
#define INFRARED_SETTINGS_MAGIC (0x1F)
|
||||
|
||||
typedef struct {
|
||||
uint8_t tx_pin;
|
||||
} InfraredSettings;
|
||||
|
||||
static const NotificationSequence*
|
||||
infrared_notification_sequences[InfraredNotificationMessageCount] = {
|
||||
&sequence_success,
|
||||
@@ -174,12 +184,6 @@ static InfraredApp* infrared_alloc(void) {
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher, InfraredViewDialogEx, dialog_ex_get_view(infrared->dialog_ex));
|
||||
|
||||
infrared->variable_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
infrared->view_dispatcher,
|
||||
InfraredViewVariableItemList,
|
||||
variable_item_list_get_view(infrared->variable_item_list));
|
||||
|
||||
infrared->button_menu = button_menu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher, InfraredViewButtonMenu, button_menu_get_view(infrared->button_menu));
|
||||
@@ -187,6 +191,12 @@ static InfraredApp* infrared_alloc(void) {
|
||||
infrared->popup = popup_alloc();
|
||||
view_dispatcher_add_view(view_dispatcher, InfraredViewPopup, popup_get_view(infrared->popup));
|
||||
|
||||
infrared->var_item_list = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher,
|
||||
InfraredViewVariableList,
|
||||
variable_item_list_get_view(infrared->var_item_list));
|
||||
|
||||
infrared->view_stack = view_stack_alloc();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher, InfraredViewStack, view_stack_get_view(infrared->view_stack));
|
||||
@@ -210,10 +220,6 @@ static InfraredApp* infrared_alloc(void) {
|
||||
infrared->button_panel = button_panel_alloc();
|
||||
infrared->progress = infrared_progress_view_alloc();
|
||||
|
||||
infrared->last_settings = infrared_last_settings_alloc();
|
||||
infrared_last_settings_load(infrared->last_settings);
|
||||
infrared_last_settings_apply(infrared->last_settings);
|
||||
|
||||
return infrared;
|
||||
}
|
||||
|
||||
@@ -241,15 +247,15 @@ static void infrared_free(InfraredApp* infrared) {
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewDialogEx);
|
||||
dialog_ex_free(infrared->dialog_ex);
|
||||
|
||||
view_dispatcher_remove_view(infrared->view_dispatcher, InfraredViewVariableItemList);
|
||||
variable_item_list_free(infrared->variable_item_list);
|
||||
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewButtonMenu);
|
||||
button_menu_free(infrared->button_menu);
|
||||
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewPopup);
|
||||
popup_free(infrared->popup);
|
||||
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewVariableList);
|
||||
variable_item_list_free(infrared->var_item_list);
|
||||
|
||||
view_dispatcher_remove_view(view_dispatcher, InfraredViewStack);
|
||||
view_stack_free(infrared->view_stack);
|
||||
|
||||
@@ -287,9 +293,6 @@ static void infrared_free(InfraredApp* infrared) {
|
||||
furi_string_free(infrared->file_path);
|
||||
furi_string_free(infrared->button_name);
|
||||
|
||||
infrared_last_settings_reset(infrared->last_settings);
|
||||
infrared_last_settings_free(infrared->last_settings);
|
||||
|
||||
free(infrared);
|
||||
}
|
||||
|
||||
@@ -447,6 +450,59 @@ void infrared_show_error_message(const InfraredApp* infrared, const char* fmt, .
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void infrared_set_tx_pin(InfraredApp* infrared, FuriHalInfraredTxPin tx_pin) {
|
||||
if(tx_pin < FuriHalInfraredTxPinMax) {
|
||||
furi_hal_infrared_set_tx_output(tx_pin);
|
||||
} else {
|
||||
FuriHalInfraredTxPin tx_pin_detected = furi_hal_infrared_detect_tx_output();
|
||||
furi_hal_infrared_set_tx_output(tx_pin_detected);
|
||||
if(tx_pin_detected != FuriHalInfraredTxPinInternal) {
|
||||
infrared_enable_otg(infrared, true);
|
||||
}
|
||||
}
|
||||
|
||||
infrared->app_state.tx_pin = tx_pin;
|
||||
}
|
||||
|
||||
void infrared_enable_otg(InfraredApp* infrared, bool enable) {
|
||||
if(enable) {
|
||||
furi_hal_power_enable_otg();
|
||||
} else {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
infrared->app_state.is_otg_enabled = enable;
|
||||
}
|
||||
|
||||
static void infrared_load_settings(InfraredApp* infrared) {
|
||||
InfraredSettings settings = {0};
|
||||
|
||||
if(!saved_struct_load(
|
||||
INFRARED_SETTINGS_PATH,
|
||||
&settings,
|
||||
sizeof(InfraredSettings),
|
||||
INFRARED_SETTINGS_MAGIC,
|
||||
INFRARED_SETTINGS_VERSION)) {
|
||||
FURI_LOG_D(TAG, "Failed to load settings, using defaults");
|
||||
}
|
||||
|
||||
infrared_set_tx_pin(infrared, settings.tx_pin);
|
||||
}
|
||||
|
||||
void infrared_save_settings(InfraredApp* infrared) {
|
||||
InfraredSettings settings = {
|
||||
.tx_pin = infrared->app_state.tx_pin,
|
||||
};
|
||||
|
||||
if(!saved_struct_save(
|
||||
INFRARED_SETTINGS_PATH,
|
||||
&settings,
|
||||
sizeof(InfraredSettings),
|
||||
INFRARED_SETTINGS_MAGIC,
|
||||
INFRARED_SETTINGS_VERSION)) {
|
||||
FURI_LOG_E(TAG, "Failed to save settings");
|
||||
}
|
||||
}
|
||||
|
||||
void infrared_signal_received_callback(void* context, InfraredWorkerSignal* received_signal) {
|
||||
furi_assert(context);
|
||||
InfraredApp* infrared = context;
|
||||
@@ -484,9 +540,10 @@ void infrared_popup_closed_callback(void* context) {
|
||||
infrared->view_dispatcher, InfraredCustomEventTypePopupClosed);
|
||||
}
|
||||
|
||||
int32_t infrared_app(char* p) {
|
||||
int32_t infrared_app(void* p) {
|
||||
InfraredApp* infrared = infrared_alloc();
|
||||
|
||||
infrared_load_settings(infrared);
|
||||
infrared_make_app_folder(infrared);
|
||||
|
||||
bool is_remote_loaded = false;
|
||||
@@ -529,6 +586,9 @@ int32_t infrared_app(char* p) {
|
||||
|
||||
view_dispatcher_run(infrared->view_dispatcher);
|
||||
|
||||
infrared_set_tx_pin(infrared, FuriHalInfraredTxPinInternal);
|
||||
infrared_enable_otg(infrared, false);
|
||||
infrared_free(infrared);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,3 +13,6 @@
|
||||
* @brief InfraredApp opaque type declaration.
|
||||
*/
|
||||
typedef struct InfraredApp InfraredApp;
|
||||
|
||||
#include <storage/storage.h>
|
||||
#define INFRARED_SETTINGS_PATH CFG_PATH("infrared.settings")
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <assets_icons.h>
|
||||
@@ -25,14 +27,12 @@
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <infrared/worker/infrared_worker.h>
|
||||
|
||||
#include "infrared_app.h"
|
||||
#include "infrared_remote.h"
|
||||
#include "infrared_brute_force.h"
|
||||
#include "infrared_custom_event.h"
|
||||
#include "infrared_last_settings.h"
|
||||
|
||||
#include "scenes/infrared_scene.h"
|
||||
#include "views/infrared_progress_view.h"
|
||||
@@ -84,11 +84,13 @@ typedef struct {
|
||||
bool is_learning_new_remote; /**< Learning new remote or adding to an existing one. */
|
||||
bool is_debug_enabled; /**< Whether to enable or disable debugging features. */
|
||||
bool is_transmitting; /**< Whether a signal is currently being transmitted. */
|
||||
bool is_otg_enabled; /**< Whether OTG power (external 5V) is enabled. */
|
||||
InfraredEditTarget edit_target : 8; /**< Selected editing target (a remote or a button). */
|
||||
InfraredEditMode edit_mode : 8; /**< Selected editing operation (rename or delete). */
|
||||
int32_t current_button_index; /**< Selected button index (move destination). */
|
||||
int32_t prev_button_index; /**< Previous button index (move source). */
|
||||
uint32_t last_transmit_time; /**< Lat time a signal was transmitted. */
|
||||
FuriHalInfraredTxPin tx_pin;
|
||||
} InfraredAppState;
|
||||
|
||||
/**
|
||||
@@ -112,7 +114,7 @@ struct InfraredApp {
|
||||
DialogEx* dialog_ex; /**< Standard view for displaying dialogs. */
|
||||
ButtonMenu* button_menu; /**< Custom view for interacting with IR remotes. */
|
||||
Popup* popup; /**< Standard view for displaying messages. */
|
||||
VariableItemList* variable_item_list;
|
||||
VariableItemList* var_item_list; /**< Standard view for displaying menus of choice items. */
|
||||
|
||||
ViewStack* view_stack; /**< Standard view for displaying stacked interfaces. */
|
||||
InfraredDebugView* debug_view; /**< Custom view for displaying debug information. */
|
||||
@@ -128,7 +130,6 @@ struct InfraredApp {
|
||||
/** Arbitrary text storage for various inputs. */
|
||||
char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1];
|
||||
InfraredAppState app_state; /**< Application state. */
|
||||
InfraredLastSettings* last_settings; /**< Last settings. */
|
||||
|
||||
void* rpc_ctx; /**< Pointer to the RPC context object. */
|
||||
};
|
||||
@@ -142,10 +143,10 @@ typedef enum {
|
||||
InfraredViewDialogEx,
|
||||
InfraredViewButtonMenu,
|
||||
InfraredViewPopup,
|
||||
InfraredViewVariableList,
|
||||
InfraredViewStack,
|
||||
InfraredViewDebugView,
|
||||
InfraredViewMove,
|
||||
InfraredViewVariableItemList,
|
||||
InfraredViewLoading,
|
||||
} InfraredView;
|
||||
|
||||
@@ -278,6 +279,32 @@ void infrared_play_notification_message(
|
||||
void infrared_show_error_message(const InfraredApp* infrared, const char* fmt, ...)
|
||||
_ATTRIBUTE((__format__(__printf__, 2, 3)));
|
||||
|
||||
/**
|
||||
* @brief Set which pin will be used to transmit infrared signals.
|
||||
*
|
||||
* Setting tx_pin to InfraredTxPinInternal will enable transmission via
|
||||
* the built-in infrared LEDs.
|
||||
*
|
||||
* @param[in] infrared pointer to the application instance.
|
||||
* @param[in] tx_pin pin to be used for signal transmission.
|
||||
*/
|
||||
void infrared_set_tx_pin(InfraredApp* infrared, FuriHalInfraredTxPin tx_pin);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable 5V at the GPIO pin 1.
|
||||
*
|
||||
* @param[in] infrared pointer to the application instance.
|
||||
* @param[in] enable boolean value corresponding to OTG state (true = enable, false = disable)
|
||||
*/
|
||||
void infrared_enable_otg(InfraredApp* infrared, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Save current settings to a file.
|
||||
*
|
||||
* @param[in] infrared pointer to the application instance.
|
||||
*/
|
||||
void infrared_save_settings(InfraredApp* infrared);
|
||||
|
||||
/**
|
||||
* @brief Common received signal callback.
|
||||
*
|
||||
|
||||
@@ -22,6 +22,9 @@ enum InfraredCustomEventType {
|
||||
InfraredCustomEventTypeRpcButtonPressIndex,
|
||||
InfraredCustomEventTypeRpcButtonRelease,
|
||||
InfraredCustomEventTypeRpcSessionClose,
|
||||
|
||||
InfraredCustomEventTypeGpioTxPinChanged,
|
||||
InfraredCustomEventTypeGpioOtgChanged,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
#include "infrared_last_settings.h"
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
|
||||
#define TAG "InfraredLastSettings"
|
||||
|
||||
#define INFRARED_LAST_SETTINGS_FILE_TYPE "Flipper Infrared Last Settings File"
|
||||
#define INFRARED_LAST_SETTINGS_FILE_VERSION 1
|
||||
#define INFRARED_LAST_SETTINGS_PATH EXT_PATH("infrared/assets/last_infrared.settings")
|
||||
|
||||
#define INFRARED_LAST_SETTINGS_FIELD_EXTPOWER "External5V"
|
||||
#define INFRARED_LAST_SETTINGS_FIELD_EXTOUT "ExternalOut"
|
||||
#define INFRARED_LAST_SETTINGS_FIELD_AUTO_DETECT "AutoDetect"
|
||||
|
||||
InfraredLastSettings* infrared_last_settings_alloc(void) {
|
||||
InfraredLastSettings* instance = malloc(sizeof(InfraredLastSettings));
|
||||
return instance;
|
||||
}
|
||||
|
||||
void infrared_last_settings_free(InfraredLastSettings* instance) {
|
||||
furi_assert(instance);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void infrared_last_settings_load(InfraredLastSettings* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
|
||||
bool temp_extpower = false;
|
||||
bool temp_extout = false;
|
||||
bool temp_auto_detect = true;
|
||||
|
||||
if(FSE_OK == storage_sd_status(storage) && INFRARED_LAST_SETTINGS_PATH &&
|
||||
flipper_format_file_open_existing(fff_data_file, INFRARED_LAST_SETTINGS_PATH)) {
|
||||
flipper_format_read_bool(
|
||||
fff_data_file, INFRARED_LAST_SETTINGS_FIELD_EXTPOWER, (bool*)&temp_extpower, 1);
|
||||
flipper_format_read_bool(
|
||||
fff_data_file, INFRARED_LAST_SETTINGS_FIELD_EXTOUT, (bool*)&temp_extout, 1);
|
||||
flipper_format_read_bool(
|
||||
fff_data_file, INFRARED_LAST_SETTINGS_FIELD_AUTO_DETECT, (bool*)&temp_auto_detect, 1);
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Error open file %s", INFRARED_LAST_SETTINGS_PATH);
|
||||
}
|
||||
|
||||
instance->ext_5v = temp_extpower;
|
||||
instance->ext_out = temp_extout;
|
||||
instance->auto_detect = temp_auto_detect;
|
||||
|
||||
flipper_format_file_close(fff_data_file);
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
bool infrared_last_settings_save(InfraredLastSettings* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
bool saved = false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(FSE_OK != storage_sd_status(storage)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Open file
|
||||
if(!flipper_format_file_open_always(file, INFRARED_LAST_SETTINGS_PATH)) break;
|
||||
|
||||
// Write header
|
||||
if(!flipper_format_write_header_cstr(
|
||||
file, INFRARED_LAST_SETTINGS_FILE_TYPE, INFRARED_LAST_SETTINGS_FILE_VERSION))
|
||||
break;
|
||||
|
||||
if(!flipper_format_insert_or_update_bool(
|
||||
file, INFRARED_LAST_SETTINGS_FIELD_EXTPOWER, &instance->ext_5v, 1))
|
||||
break;
|
||||
if(!flipper_format_insert_or_update_bool(
|
||||
file, INFRARED_LAST_SETTINGS_FIELD_EXTOUT, &instance->ext_out, 1))
|
||||
break;
|
||||
if(!flipper_format_insert_or_update_bool(
|
||||
file, INFRARED_LAST_SETTINGS_FIELD_AUTO_DETECT, &instance->auto_detect, 1))
|
||||
break;
|
||||
|
||||
saved = true;
|
||||
} while(0);
|
||||
|
||||
if(!saved) {
|
||||
FURI_LOG_E(TAG, "Error save file %s", INFRARED_LAST_SETTINGS_PATH);
|
||||
}
|
||||
|
||||
flipper_format_file_close(file);
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
void infrared_last_settings_apply(InfraredLastSettings* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
instance->_otg_was_enabled = furi_hal_power_is_otg_enabled();
|
||||
furi_hal_infrared_set_auto_detect(instance->auto_detect);
|
||||
if(!instance->auto_detect) {
|
||||
furi_hal_infrared_set_debug_out(instance->ext_out);
|
||||
if(instance->ext_5v) {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
} else if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
} else if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
}
|
||||
|
||||
void infrared_last_settings_reset(InfraredLastSettings* instance) {
|
||||
furi_assert(instance);
|
||||
|
||||
if(instance->_otg_was_enabled != furi_hal_power_is_otg_enabled()) {
|
||||
if(instance->_otg_was_enabled) {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
} else {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <lib/flipper_format/flipper_format.h>
|
||||
|
||||
typedef struct {
|
||||
bool ext_5v;
|
||||
bool ext_out;
|
||||
bool auto_detect;
|
||||
|
||||
bool _otg_was_enabled;
|
||||
} InfraredLastSettings;
|
||||
|
||||
InfraredLastSettings* infrared_last_settings_alloc(void);
|
||||
void infrared_last_settings_free(InfraredLastSettings* instance);
|
||||
void infrared_last_settings_load(InfraredLastSettings* instance);
|
||||
bool infrared_last_settings_save(InfraredLastSettings* instance);
|
||||
void infrared_last_settings_apply(InfraredLastSettings* instance);
|
||||
void infrared_last_settings_reset(InfraredLastSettings* instance);
|
||||
@@ -4232,3 +4232,52 @@ type: parsed
|
||||
protocol: NECext
|
||||
address: 87 7C 00 00
|
||||
command: 25 DA 00 00
|
||||
#
|
||||
# Model: Dutch Originals Sound Bar
|
||||
name: Power
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 07 00 00 00
|
||||
#
|
||||
name: Next
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 15 00 00 00
|
||||
#
|
||||
name: Prev
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 15 00 00 00
|
||||
#
|
||||
name: Play
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 6A 00 00 00
|
||||
#
|
||||
name: Pause
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 6A 00 00 00
|
||||
#
|
||||
name: Mute
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 09 00 00 00
|
||||
#
|
||||
name: Vol_up
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 5E 00 00 00
|
||||
#
|
||||
name: Vol_dn
|
||||
type: parsed
|
||||
protocol: NEC
|
||||
address: 00 00 00 00
|
||||
command: 85 00 00 00
|
||||
|
||||
@@ -23,7 +23,7 @@ ADD_SCENE(infrared, universal_audio, UniversalAudio)
|
||||
ADD_SCENE(infrared, universal_led, UniversalLED)
|
||||
ADD_SCENE(infrared, universal_ac, UniversalAC)
|
||||
ADD_SCENE(infrared, universal_fan, UniversalFan)
|
||||
ADD_SCENE(infrared, gpio_settings, GpioSettings)
|
||||
ADD_SCENE(infrared, debug, Debug)
|
||||
ADD_SCENE(infrared, error_databases, ErrorDatabases)
|
||||
ADD_SCENE(infrared, debug_settings, DebugSettings)
|
||||
ADD_SCENE(infrared, rpc, Rpc)
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
#include "../infrared_app_i.h"
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
|
||||
uint8_t value_index_ir;
|
||||
|
||||
#define DEB_PINS_COUNT (sizeof(infrared_debug_cfg_variables_text) / sizeof(char* const))
|
||||
const char* const infrared_debug_cfg_variables_text[] = {
|
||||
"Internal",
|
||||
"2 (A7)",
|
||||
};
|
||||
|
||||
static void infrared_scene_debug_settings_auto_detect_changed(VariableItem* item) {
|
||||
InfraredApp* infrared = variable_item_get_context(item);
|
||||
bool value = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, value ? "ON" : "OFF");
|
||||
|
||||
// enable/disable other list items
|
||||
VariableItemList* var_item_list = infrared->variable_item_list;
|
||||
variable_item_set_locked(variable_item_list_get(var_item_list, 1), value, NULL);
|
||||
variable_item_set_locked(variable_item_list_get(var_item_list, 2), value, NULL);
|
||||
|
||||
infrared->last_settings->auto_detect = value;
|
||||
infrared_last_settings_save(infrared->last_settings);
|
||||
|
||||
furi_hal_infrared_set_auto_detect(infrared->last_settings->auto_detect);
|
||||
if(!infrared->last_settings->auto_detect) {
|
||||
furi_hal_infrared_set_debug_out(infrared->last_settings->ext_out);
|
||||
if(infrared->last_settings->ext_5v) {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
} else if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
} else if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
}
|
||||
|
||||
static void infrared_scene_debug_settings_pin_changed(VariableItem* item) {
|
||||
InfraredApp* infrared = variable_item_get_context(item);
|
||||
value_index_ir = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, infrared_debug_cfg_variables_text[value_index_ir]);
|
||||
|
||||
furi_hal_infrared_set_debug_out(value_index_ir);
|
||||
|
||||
infrared->last_settings->ext_out = value_index_ir == 1;
|
||||
infrared_last_settings_save(infrared->last_settings);
|
||||
}
|
||||
|
||||
static void infrared_scene_debug_settings_power_changed(VariableItem* item) {
|
||||
InfraredApp* infrared = variable_item_get_context(item);
|
||||
bool value = variable_item_get_current_value_index(item);
|
||||
if(value) {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
}
|
||||
variable_item_set_current_value_text(item, value ? "ON" : "OFF");
|
||||
|
||||
infrared->last_settings->ext_5v = value;
|
||||
infrared_last_settings_save(infrared->last_settings);
|
||||
}
|
||||
|
||||
static void infrared_debug_settings_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||
InfraredApp* infrared = context;
|
||||
view_dispatcher_send_custom_event(infrared->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void infrared_scene_debug_settings_on_enter(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
|
||||
VariableItemList* variable_item_list = infrared->variable_item_list;
|
||||
variable_item_list_set_enter_callback(
|
||||
variable_item_list, infrared_debug_settings_start_var_list_enter_callback, infrared);
|
||||
|
||||
VariableItem* item = variable_item_list_add(
|
||||
variable_item_list,
|
||||
"Auto detect",
|
||||
2,
|
||||
infrared_scene_debug_settings_auto_detect_changed,
|
||||
infrared);
|
||||
|
||||
bool auto_detect = infrared->last_settings->auto_detect;
|
||||
|
||||
variable_item_set_current_value_index(item, auto_detect);
|
||||
variable_item_set_current_value_text(item, auto_detect ? "ON" : "OFF");
|
||||
|
||||
item = variable_item_list_add(
|
||||
variable_item_list,
|
||||
"Send signal to",
|
||||
DEB_PINS_COUNT,
|
||||
infrared_scene_debug_settings_pin_changed,
|
||||
infrared);
|
||||
|
||||
value_index_ir = infrared->last_settings->ext_out;
|
||||
|
||||
variable_item_list_set_enter_callback(
|
||||
variable_item_list, infrared_debug_settings_start_var_list_enter_callback, infrared);
|
||||
|
||||
variable_item_set_current_value_index(item, value_index_ir);
|
||||
variable_item_set_current_value_text(item, infrared_debug_cfg_variables_text[value_index_ir]);
|
||||
variable_item_set_locked(item, auto_detect, "Disable auto detect");
|
||||
|
||||
item = variable_item_list_add(
|
||||
variable_item_list,
|
||||
"Ext Module 5v",
|
||||
2,
|
||||
infrared_scene_debug_settings_power_changed,
|
||||
infrared);
|
||||
bool enabled = infrared->last_settings->ext_5v;
|
||||
variable_item_set_current_value_index(item, enabled);
|
||||
variable_item_set_current_value_text(item, enabled ? "ON" : "OFF");
|
||||
variable_item_set_locked(item, auto_detect, "Disable auto detect");
|
||||
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewVariableItemList);
|
||||
}
|
||||
|
||||
bool infrared_scene_debug_settings_on_event(void* context, SceneManagerEvent event) {
|
||||
InfraredApp* infrared = context;
|
||||
UNUSED(infrared);
|
||||
UNUSED(event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void infrared_scene_debug_settings_on_exit(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
variable_item_list_reset(infrared->variable_item_list);
|
||||
}
|
||||
102
applications/main/infrared/scenes/infrared_scene_gpio_settings.c
Normal file
102
applications/main/infrared/scenes/infrared_scene_gpio_settings.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include "../infrared_app_i.h"
|
||||
|
||||
static const char* infrared_scene_gpio_settings_pin_text[] = {
|
||||
"Flipper",
|
||||
"2 (A7)",
|
||||
"Detect",
|
||||
};
|
||||
|
||||
static const char* infrared_scene_gpio_settings_otg_text[] = {
|
||||
"OFF",
|
||||
"ON",
|
||||
};
|
||||
|
||||
static void infrared_scene_gpio_settings_pin_change_callback(VariableItem* item) {
|
||||
InfraredApp* infrared = variable_item_get_context(item);
|
||||
const uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, infrared_scene_gpio_settings_pin_text[index]);
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher,
|
||||
infrared_custom_event_pack(InfraredCustomEventTypeGpioTxPinChanged, index));
|
||||
}
|
||||
|
||||
static void infrared_scene_gpio_settings_otg_change_callback(VariableItem* item) {
|
||||
InfraredApp* infrared = variable_item_get_context(item);
|
||||
const uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, infrared_scene_gpio_settings_otg_text[index]);
|
||||
view_dispatcher_send_custom_event(
|
||||
infrared->view_dispatcher,
|
||||
infrared_custom_event_pack(InfraredCustomEventTypeGpioOtgChanged, index));
|
||||
}
|
||||
|
||||
static void infrared_scene_gpio_settings_init(InfraredApp* infrared) {
|
||||
VariableItemList* var_item_list = infrared->var_item_list;
|
||||
VariableItem* item;
|
||||
uint8_t value_index;
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
"Signal Output",
|
||||
COUNT_OF(infrared_scene_gpio_settings_pin_text),
|
||||
infrared_scene_gpio_settings_pin_change_callback,
|
||||
infrared);
|
||||
|
||||
value_index = infrared->app_state.tx_pin;
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, infrared_scene_gpio_settings_pin_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
"5V on GPIO",
|
||||
COUNT_OF(infrared_scene_gpio_settings_otg_text),
|
||||
infrared_scene_gpio_settings_otg_change_callback,
|
||||
infrared);
|
||||
|
||||
if(infrared->app_state.tx_pin < FuriHalInfraredTxPinMax) {
|
||||
value_index = infrared->app_state.is_otg_enabled;
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(
|
||||
item, infrared_scene_gpio_settings_otg_text[value_index]);
|
||||
} else {
|
||||
variable_item_set_values_count(item, 1);
|
||||
variable_item_set_current_value_index(item, 0);
|
||||
variable_item_set_current_value_text(item, "Auto");
|
||||
}
|
||||
}
|
||||
|
||||
void infrared_scene_gpio_settings_on_enter(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
infrared_scene_gpio_settings_init(infrared);
|
||||
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewVariableList);
|
||||
}
|
||||
|
||||
bool infrared_scene_gpio_settings_on_event(void* context, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
InfraredApp* infrared = context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
const uint16_t custom_event_type = infrared_custom_event_get_type(event.event);
|
||||
const uint16_t custom_event_value = infrared_custom_event_get_value(event.event);
|
||||
|
||||
if(custom_event_type == InfraredCustomEventTypeGpioTxPinChanged) {
|
||||
infrared_set_tx_pin(infrared, custom_event_value);
|
||||
variable_item_list_reset(infrared->var_item_list);
|
||||
infrared_scene_gpio_settings_init(infrared);
|
||||
} else if(custom_event_type == InfraredCustomEventTypeGpioOtgChanged) {
|
||||
infrared_enable_otg(infrared, custom_event_value);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void infrared_scene_gpio_settings_on_exit(void* context) {
|
||||
InfraredApp* infrared = context;
|
||||
variable_item_list_reset(infrared->var_item_list);
|
||||
infrared_save_settings(infrared);
|
||||
}
|
||||
@@ -6,7 +6,7 @@ void infrared_scene_learn_done_on_enter(void* context) {
|
||||
|
||||
if(infrared->app_state.is_learning_new_remote) {
|
||||
popup_set_icon(popup, 48, 6, &I_DolphinDone_80x58);
|
||||
popup_set_header(popup, "New remote\ncreated!", 0, 0, AlignLeft, AlignTop);
|
||||
popup_set_header(popup, "Success!", 10, 12, AlignLeft, AlignTop);
|
||||
} else {
|
||||
popup_set_icon(popup, 36, 5, &I_DolphinSaved_92x58);
|
||||
popup_set_header(popup, "Saved", 15, 19, AlignLeft, AlignBottom);
|
||||
|
||||
@@ -4,7 +4,7 @@ enum SubmenuIndex {
|
||||
SubmenuIndexUniversalRemotes,
|
||||
SubmenuIndexLearnNewRemote,
|
||||
SubmenuIndexSavedRemotes,
|
||||
SubmenuIndexDebugSettings,
|
||||
SubmenuIndexGpioSettings,
|
||||
SubmenuIndexLearnNewRemoteRaw,
|
||||
SubmenuIndexDebug
|
||||
};
|
||||
@@ -40,7 +40,7 @@ void infrared_scene_start_on_enter(void* context) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"GPIO Settings",
|
||||
SubmenuIndexDebugSettings,
|
||||
SubmenuIndexGpioSettings,
|
||||
infrared_scene_start_submenu_callback,
|
||||
infrared);
|
||||
|
||||
@@ -80,7 +80,6 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_set_scene_state(scene_manager, InfraredSceneStart, submenu_index);
|
||||
if(submenu_index == SubmenuIndexUniversalRemotes) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneUniversal);
|
||||
consumed = true;
|
||||
} else if(
|
||||
submenu_index == SubmenuIndexLearnNewRemote ||
|
||||
submenu_index == SubmenuIndexLearnNewRemoteRaw) {
|
||||
@@ -90,18 +89,16 @@ bool infrared_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
infrared->worker, submenu_index == SubmenuIndexLearnNewRemote);
|
||||
infrared->app_state.is_learning_new_remote = true;
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneLearn);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexSavedRemotes) {
|
||||
furi_string_set(infrared->file_path, INFRARED_APP_FOLDER);
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneRemoteList);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexGpioSettings) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneGpioSettings);
|
||||
} else if(submenu_index == SubmenuIndexDebug) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneDebug);
|
||||
consumed = true;
|
||||
} else if(submenu_index == SubmenuIndexDebugSettings) {
|
||||
scene_manager_next_scene(scene_manager, InfraredSceneDebugSettings);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
||||
@@ -34,7 +34,7 @@ static void infrared_move_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, canvas_width(canvas) / 2, 0, AlignCenter, AlignTop, "Select a button to move");
|
||||
canvas, canvas_width(canvas) / 2, 0, AlignCenter, AlignTop, "Select a Button to Move");
|
||||
|
||||
const size_t btn_number = InfraredMoveViewItemArray_size(model->labels);
|
||||
const bool show_scrollbar = btn_number > LIST_ITEMS;
|
||||
|
||||
@@ -72,16 +72,19 @@ bool bt_keys_storage_load(BtKeysStorage* instance) {
|
||||
bool loaded = false;
|
||||
do {
|
||||
// Get payload size
|
||||
uint8_t magic = 0, version = 0;
|
||||
size_t payload_size = 0;
|
||||
if(!saved_struct_get_payload_size(
|
||||
furi_string_get_cstr(instance->file_path),
|
||||
BT_KEYS_STORAGE_MAGIC,
|
||||
BT_KEYS_STORAGE_VERSION,
|
||||
&payload_size)) {
|
||||
if(!saved_struct_get_metadata(
|
||||
furi_string_get_cstr(instance->file_path), &magic, &version, &payload_size)) {
|
||||
FURI_LOG_E(TAG, "Failed to read payload size");
|
||||
break;
|
||||
}
|
||||
|
||||
if(magic != BT_KEYS_STORAGE_MAGIC || version != BT_KEYS_STORAGE_VERSION) {
|
||||
FURI_LOG_E(TAG, "Saved data version is mismatched");
|
||||
break;
|
||||
}
|
||||
|
||||
if(payload_size > instance->nvm_sram_buff_size) {
|
||||
FURI_LOG_E(TAG, "Saved data doesn't fit ram buffer");
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@ bool bt_settings_load(BtSettings* bt_settings) {
|
||||
BT_SETTINGS_PATH, bt_settings, sizeof(BtSettings), BT_SETTINGS_MAGIC, BT_SETTINGS_VERSION);
|
||||
}
|
||||
|
||||
bool bt_settings_save(BtSettings* bt_settings) {
|
||||
bool bt_settings_save(const BtSettings* bt_settings) {
|
||||
furi_assert(bt_settings);
|
||||
|
||||
return saved_struct_save(
|
||||
|
||||
@@ -15,7 +15,7 @@ typedef struct {
|
||||
|
||||
bool bt_settings_load(BtSettings* bt_settings);
|
||||
|
||||
bool bt_settings_save(BtSettings* bt_settings);
|
||||
bool bt_settings_save(const BtSettings* bt_settings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
typedef struct {
|
||||
FuriTimer* timer;
|
||||
FuriString* enter_pin_string;
|
||||
} DesktopScenePinInputState;
|
||||
|
||||
static void desktop_scene_locked_light_red(bool value) {
|
||||
@@ -77,6 +78,18 @@ static void desktop_scene_pin_input_timer_callback(void* context) {
|
||||
desktop->view_dispatcher, DesktopPinInputEventResetWrongPinLabel);
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_scene_pin_input_update_wrong_count(DesktopScenePinInputState* state, Desktop* desktop) {
|
||||
uint32_t attempts = furi_hal_rtc_get_pin_fails();
|
||||
if(attempts > 0) {
|
||||
furi_string_printf(state->enter_pin_string, "Wrong Attempts: %lu", attempts);
|
||||
desktop_view_pin_input_set_label_tertiary(
|
||||
desktop->pin_input_view, 64, 60, furi_string_get_cstr(state->enter_pin_string));
|
||||
} else {
|
||||
desktop_view_pin_input_set_label_tertiary(desktop->pin_input_view, 64, 60, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void desktop_scene_pin_input_on_enter(void* context) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
|
||||
@@ -89,6 +102,7 @@ void desktop_scene_pin_input_on_enter(void* context) {
|
||||
desktop->pin_input_view, desktop_scene_pin_input_done_callback);
|
||||
|
||||
DesktopScenePinInputState* state = malloc(sizeof(DesktopScenePinInputState));
|
||||
state->enter_pin_string = furi_string_alloc();
|
||||
state->timer =
|
||||
furi_timer_alloc(desktop_scene_pin_input_timer_callback, FuriTimerTypeOnce, desktop);
|
||||
scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state);
|
||||
@@ -96,6 +110,7 @@ void desktop_scene_pin_input_on_enter(void* context) {
|
||||
desktop_view_pin_input_hide_pin(desktop->pin_input_view, true);
|
||||
desktop_view_pin_input_set_label_button(desktop->pin_input_view, "OK");
|
||||
desktop_view_pin_input_set_label_secondary(desktop->pin_input_view, 44, 25, "Enter PIN:");
|
||||
desktop_scene_pin_input_update_wrong_count(state, desktop);
|
||||
desktop_view_pin_input_set_pin_position(desktop->pin_input_view, 64, 37);
|
||||
desktop_view_pin_input_reset_pin(desktop->pin_input_view);
|
||||
|
||||
@@ -106,7 +121,8 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
||||
Desktop* desktop = (Desktop*)context;
|
||||
bool consumed = false;
|
||||
uint32_t pin_timeout = 0;
|
||||
|
||||
DesktopScenePinInputState* state = (DesktopScenePinInputState*)scene_manager_get_scene_state(
|
||||
desktop->scene_manager, DesktopScenePinInput);
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case DesktopPinInputEventUnlockFailed:
|
||||
@@ -122,6 +138,7 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
desktop->pin_input_view, 25, 25, "Wrong PIN try again:");
|
||||
desktop_scene_pin_input_set_timer(desktop, true, WRONG_PIN_HEADER_TIMEOUT);
|
||||
desktop_scene_pin_input_update_wrong_count(state, desktop);
|
||||
desktop_view_pin_input_reset_pin(desktop->pin_input_view);
|
||||
}
|
||||
consumed = true;
|
||||
@@ -131,6 +148,7 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) {
|
||||
desktop_view_pin_input_set_label_primary(desktop->pin_input_view, 0, 0, NULL);
|
||||
desktop_view_pin_input_set_label_secondary(
|
||||
desktop->pin_input_view, 44, 25, "Enter PIN:");
|
||||
desktop_scene_pin_input_update_wrong_count(state, desktop);
|
||||
consumed = true;
|
||||
break;
|
||||
case DesktopPinInputEventUnlocked:
|
||||
@@ -158,5 +176,6 @@ void desktop_scene_pin_input_on_exit(void* context) {
|
||||
desktop->scene_manager, DesktopScenePinInput);
|
||||
|
||||
furi_timer_free(state->timer);
|
||||
furi_string_free(state->enter_pin_string);
|
||||
free(state);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ typedef struct {
|
||||
const char* secondary_str;
|
||||
uint8_t secondary_str_x;
|
||||
uint8_t secondary_str_y;
|
||||
const char* tertiary_str;
|
||||
uint8_t tertiary_str_x;
|
||||
uint8_t tertiary_str_y;
|
||||
const char* button_label;
|
||||
} DesktopViewPinInputModel;
|
||||
|
||||
@@ -167,6 +170,17 @@ static void desktop_view_pin_input_draw(Canvas* canvas, void* context) {
|
||||
canvas_draw_str(
|
||||
canvas, model->secondary_str_x, model->secondary_str_y, model->secondary_str);
|
||||
}
|
||||
|
||||
if(model->tertiary_str && model->pin.length == 0) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
model->tertiary_str_x,
|
||||
model->tertiary_str_y,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
model->tertiary_str);
|
||||
}
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_timer_callback(void* context) {
|
||||
@@ -294,6 +308,20 @@ void desktop_view_pin_input_set_label_secondary(
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_label_tertiary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
DesktopViewPinInputModel* model = view_get_model(pin_input->view);
|
||||
model->tertiary_str = label;
|
||||
model->tertiary_str_x = x;
|
||||
model->tertiary_str_y = y;
|
||||
view_commit_model(pin_input->view, true);
|
||||
}
|
||||
|
||||
void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y) {
|
||||
furi_assert(pin_input);
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@ void desktop_view_pin_input_set_label_secondary(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label);
|
||||
void desktop_view_pin_input_set_label_tertiary(
|
||||
DesktopViewPinInput* pin_input,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
const char* label);
|
||||
void desktop_view_pin_input_set_pin_position(DesktopViewPinInput* pin_input, uint8_t x, uint8_t y);
|
||||
View* desktop_view_pin_input_get_view(DesktopViewPinInput*);
|
||||
void desktop_view_pin_input_set_done_callback(
|
||||
|
||||
@@ -18,7 +18,7 @@ bool expansion_settings_load(ExpansionSettings* settings) {
|
||||
EXPANSION_SETTINGS_VERSION);
|
||||
}
|
||||
|
||||
bool expansion_settings_save(ExpansionSettings* settings) {
|
||||
bool expansion_settings_save(const ExpansionSettings* settings) {
|
||||
furi_assert(settings);
|
||||
return saved_struct_save(
|
||||
EXPANSION_SETTINGS_PATH,
|
||||
|
||||
@@ -36,7 +36,7 @@ bool expansion_settings_load(ExpansionSettings* settings);
|
||||
* @param[in] settings pointer to an ExpansionSettings instance to save settings from.
|
||||
* @returns true if the settings were successfully saved, false otherwise.
|
||||
*/
|
||||
bool expansion_settings_save(ExpansionSettings* settings);
|
||||
bool expansion_settings_save(const ExpansionSettings* settings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ static void text_box_insert_endline(Canvas* canvas, TextBoxModel* model) {
|
||||
line_num++;
|
||||
model->text = furi_string_get_cstr(model->text_formatted);
|
||||
model->text_pos = (char*)model->text;
|
||||
uint8_t lines_on_screen = 56 / canvas_current_font_height(canvas);
|
||||
size_t lines_on_screen = 56 / canvas_current_font_height(canvas);
|
||||
if(model->focus == TextBoxFocusEnd && line_num > lines_on_screen) {
|
||||
// Set text position to 5th line from the end
|
||||
const char* end = model->text + furi_string_size(model->text_formatted);
|
||||
|
||||
@@ -151,7 +151,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
||||
}
|
||||
|
||||
if(power->state == PowerStateCharging) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
// TODO: replace -1 magic for uint8_t with re-framing
|
||||
if(battery_icon == BatteryIconPercent) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
@@ -234,7 +234,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_icon(canvas, 8, -1, &I_Charging_lightning_9x10);
|
||||
}
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
}
|
||||
} else {
|
||||
canvas_draw_box(canvas, 8, 3, 8, 2);
|
||||
|
||||
@@ -26,7 +26,7 @@ void desktop_settings_scene_pin_disable_on_enter(void* context) {
|
||||
popup_set_context(app->popup, app);
|
||||
popup_set_callback(app->popup, pin_disable_back_callback);
|
||||
popup_set_icon(app->popup, 0, 2, &I_DolphinMafia_119x62);
|
||||
popup_set_header(app->popup, "Deleted", 80, 19, AlignLeft, AlignBottom);
|
||||
popup_set_header(app->popup, "PIN\nDeleted!", 100, 0, AlignCenter, AlignTop);
|
||||
popup_set_timeout(app->popup, 1500);
|
||||
popup_enable_timeout(app->popup);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewIdPopup);
|
||||
|
||||
@@ -23,7 +23,7 @@ void desktop_settings_scene_pin_menu_on_enter(void* context) {
|
||||
if(!desktop_pin_is_valid(&app->desktop->settings.pin_code)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Set Pin",
|
||||
"Set PIN",
|
||||
SCENE_EVENT_SET_PIN,
|
||||
desktop_settings_scene_pin_menu_submenu_callback,
|
||||
app);
|
||||
@@ -31,7 +31,7 @@ void desktop_settings_scene_pin_menu_on_enter(void* context) {
|
||||
} else {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change Pin",
|
||||
"Change PIN",
|
||||
SCENE_EVENT_CHANGE_PIN,
|
||||
desktop_settings_scene_pin_menu_submenu_callback,
|
||||
app);
|
||||
@@ -44,7 +44,7 @@ void desktop_settings_scene_pin_menu_on_enter(void* context) {
|
||||
app);
|
||||
}
|
||||
|
||||
submenu_set_header(app->submenu, "Pin Code Settings:");
|
||||
submenu_set_header(app->submenu, "PIN Code Settings");
|
||||
submenu_set_selected_item(app->submenu, app->menu_idx);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewMenu);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ void power_settings_scene_power_off_on_enter(void* context) {
|
||||
PowerSettingsApp* app = context;
|
||||
DialogEx* dialog = app->dialog;
|
||||
|
||||
dialog_ex_set_header(dialog, "Turn Off Device?", 64, 2, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(dialog, "Turn OFF Device?", 64, 2, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
dialog, " I will be\nwaiting for\n you here", 78, 16, AlignLeft, AlignTop);
|
||||
dialog_ex_set_icon(dialog, 21, 13, &I_Cry_dolph_55x52);
|
||||
|
||||
@@ -6,6 +6,7 @@ App(
|
||||
"updater_app",
|
||||
"storage_move_to_sd",
|
||||
"js_app",
|
||||
"js_app_start",
|
||||
"findmy_startup",
|
||||
# "archive",
|
||||
],
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB |
BIN
applications/system/hid_app/assets/DolphinDone_80x58.png
Normal file
BIN
applications/system/hid_app/assets/DolphinDone_80x58.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -4,26 +4,9 @@
|
||||
#include "views.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include "hid_icons.h"
|
||||
|
||||
#define TAG "HidApp"
|
||||
|
||||
enum HidDebugSubmenuIndex {
|
||||
HidSubmenuIndexKeynote,
|
||||
HidSubmenuIndexKeynoteVertical,
|
||||
HidSubmenuIndexKeyboard,
|
||||
HidSubmenuIndexNumpad,
|
||||
HidSubmenuIndexMedia,
|
||||
HidSubmenuIndexMusicMacOs,
|
||||
HidSubmenuIndexMovie,
|
||||
HidSubmenuIndexTikTok,
|
||||
HidSubmenuIndexMouse,
|
||||
HidSubmenuIndexMouseClicker,
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
HidSubmenuIndexPushToTalk,
|
||||
HidSubmenuIndexRemovePairing,
|
||||
};
|
||||
|
||||
bool hid_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
@@ -33,10 +16,7 @@ bool hid_custom_event_callback(void* context, uint32_t event) {
|
||||
bool hid_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
FURI_LOG_D("HID", "Back event");
|
||||
app->view_id = HidViewSubmenu;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewSubmenu);
|
||||
return true;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
void bt_hid_remove_pairing(Hid* app) {
|
||||
@@ -53,63 +33,12 @@ void bt_hid_remove_pairing(Hid* app) {
|
||||
furi_hal_bt_start_advertising();
|
||||
}
|
||||
|
||||
static void hid_submenu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
if(index == HidSubmenuIndexKeynote) {
|
||||
app->view_id = HidViewKeynote;
|
||||
hid_keynote_set_orientation(app->hid_keynote, false);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote);
|
||||
} else if(index == HidSubmenuIndexKeynoteVertical) {
|
||||
app->view_id = HidViewKeynote;
|
||||
hid_keynote_set_orientation(app->hid_keynote, true);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote);
|
||||
} else if(index == HidSubmenuIndexKeyboard) {
|
||||
app->view_id = HidViewKeyboard;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeyboard);
|
||||
} else if(index == HidSubmenuIndexNumpad) {
|
||||
app->view_id = HidViewNumpad;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewNumpad);
|
||||
} else if(index == HidSubmenuIndexMedia) {
|
||||
app->view_id = HidViewMedia;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMedia);
|
||||
} else if(index == HidSubmenuIndexMusicMacOs) {
|
||||
app->view_id = HidViewMusicMacOs;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMusicMacOs);
|
||||
} else if(index == HidSubmenuIndexMovie) {
|
||||
app->view_id = HidViewMovie;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMovie);
|
||||
} else if(index == HidSubmenuIndexMouse) {
|
||||
app->view_id = HidViewMouse;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouse);
|
||||
} else if(index == HidSubmenuIndexTikTok) {
|
||||
app->view_id = BtHidViewTikTok;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
|
||||
} else if(index == HidSubmenuIndexMouseClicker) {
|
||||
app->view_id = HidViewMouseClicker;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseClicker);
|
||||
} else if(index == HidSubmenuIndexMouseJiggler) {
|
||||
app->view_id = HidViewMouseJiggler;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
|
||||
} else if(index == HidSubmenuIndexPushToTalk) {
|
||||
app->view_id = HidViewPushToTalkMenu;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewPushToTalkMenu);
|
||||
} else if(index == HidSubmenuIndexRemovePairing) {
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneUnpair);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_hid_connection_status_changed_callback(BtStatus status, void* context) {
|
||||
furi_assert(context);
|
||||
Hid* hid = context;
|
||||
bool connected = (status == BtStatusConnected);
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(connected) {
|
||||
notification_internal_message(hid->notifications, &sequence_set_blue_255);
|
||||
} else {
|
||||
notification_internal_message(hid->notifications, &sequence_reset_blue);
|
||||
}
|
||||
#endif
|
||||
const bool connected = (status == BtStatusConnected);
|
||||
notification_internal_message(
|
||||
hid->notifications, connected ? &sequence_set_blue_255 : &sequence_reset_blue);
|
||||
hid_keynote_set_connected_status(hid->hid_keynote, connected);
|
||||
hid_keyboard_set_connected_status(hid->hid_keyboard, connected);
|
||||
hid_numpad_set_connected_status(hid->hid_numpad, connected);
|
||||
@@ -123,17 +52,12 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
|
||||
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
|
||||
}
|
||||
|
||||
static uint32_t hid_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
static uint32_t hid_ptt_menu_view(void* context) {
|
||||
UNUSED(context);
|
||||
return HidViewPushToTalkMenu;
|
||||
}
|
||||
|
||||
Hid* hid_alloc(void) {
|
||||
Hid* hid_alloc() {
|
||||
Hid* app = malloc(sizeof(Hid));
|
||||
|
||||
// Gui
|
||||
@@ -148,81 +72,18 @@ Hid* hid_alloc(void) {
|
||||
// View dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
view_dispatcher_set_navigation_event_callback(app->view_dispatcher, hid_back_event_callback);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(app->view_dispatcher, hid_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(app->view_dispatcher, hid_back_event_callback);
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Scene Manager
|
||||
app->scene_manager = scene_manager_alloc(&hid_scene_handlers, app);
|
||||
|
||||
// Device Type Submenu view
|
||||
app->device_type_submenu = submenu_alloc();
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Keynote", HidSubmenuIndexKeynote, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Keynote Vertical",
|
||||
HidSubmenuIndexKeynoteVertical,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Numpad", HidSubmenuIndexNumpad, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Media", HidSubmenuIndexMedia, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Apple Music macOS",
|
||||
HidSubmenuIndexMusicMacOs,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Movie", HidSubmenuIndexMovie, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu, "Mouse", HidSubmenuIndexMouse, hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"TikTok / YT Shorts",
|
||||
HidSubmenuIndexTikTok,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Mouse Clicker",
|
||||
HidSubmenuIndexMouseClicker,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Mouse Jiggler",
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"PushToTalk",
|
||||
HidSubmenuIndexPushToTalk,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"Remove Pairing",
|
||||
HidSubmenuIndexRemovePairing,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
view_set_previous_callback(submenu_get_view(app->device_type_submenu), hid_exit);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->device_type_submenu));
|
||||
app->view_id = HidViewSubmenu;
|
||||
return app;
|
||||
}
|
||||
app->submenu = submenu_alloc();
|
||||
|
||||
Hid* hid_app_alloc_view(void* context) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
view_dispatcher_add_view(app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
// Dialog view
|
||||
app->dialog = dialog_ex_alloc();
|
||||
@@ -307,7 +168,7 @@ void hid_free(Hid* app) {
|
||||
#endif
|
||||
// Free views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewSubmenu);
|
||||
submenu_free(app->device_type_submenu);
|
||||
submenu_free(app->submenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewDialog);
|
||||
dialog_ex_free(app->dialog);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, HidViewPopup);
|
||||
@@ -354,18 +215,16 @@ void hid_free(Hid* app) {
|
||||
int32_t hid_usb_app(void* p) {
|
||||
UNUSED(p);
|
||||
Hid* app = hid_alloc();
|
||||
app = hid_app_alloc_view(app);
|
||||
|
||||
FURI_LOG_D("HID", "Starting as USB app");
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
|
||||
|
||||
bt_hid_connection_status_changed_callback(BtStatusConnected, app);
|
||||
|
||||
dolphin_deed(DolphinDeedPluginStart);
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneMain);
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneStart);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
@@ -379,7 +238,6 @@ int32_t hid_usb_app(void* p) {
|
||||
int32_t hid_ble_app(void* p) {
|
||||
UNUSED(p);
|
||||
Hid* app = hid_alloc();
|
||||
app = hid_app_alloc_view(app);
|
||||
|
||||
FURI_LOG_D("HID", "Starting as BLE app");
|
||||
|
||||
@@ -409,7 +267,7 @@ int32_t hid_ble_app(void* p) {
|
||||
|
||||
dolphin_deed(DolphinDeedPluginStart);
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneMain);
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneStart);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
|
||||
@@ -35,11 +35,6 @@
|
||||
|
||||
#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys"
|
||||
|
||||
typedef enum {
|
||||
HidTransportUsb,
|
||||
HidTransportBle,
|
||||
} HidTransport;
|
||||
|
||||
typedef struct Hid Hid;
|
||||
|
||||
struct Hid {
|
||||
@@ -49,7 +44,7 @@ struct Hid {
|
||||
NotificationApp* notifications;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
Submenu* device_type_submenu;
|
||||
Submenu* submenu;
|
||||
DialogEx* dialog;
|
||||
Popup* popup;
|
||||
HidKeynote* hid_keynote;
|
||||
@@ -64,10 +59,8 @@ struct Hid {
|
||||
HidTikTok* hid_tiktok;
|
||||
HidPushToTalk* hid_ptt;
|
||||
HidPushToTalkMenu* hid_ptt_menu;
|
||||
|
||||
HidTransport transport;
|
||||
uint32_t view_id;
|
||||
};
|
||||
|
||||
void bt_hid_remove_pairing(Hid* app);
|
||||
|
||||
void hid_hal_keyboard_press(Hid* instance, uint16_t event);
|
||||
@@ -82,4 +75,4 @@ void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy);
|
||||
void hid_hal_mouse_scroll(Hid* instance, int8_t delta);
|
||||
void hid_hal_mouse_press(Hid* instance, uint16_t event);
|
||||
void hid_hal_mouse_release(Hid* instance, uint16_t event);
|
||||
void hid_hal_mouse_release_all(Hid* instance);
|
||||
void hid_hal_mouse_release_all(Hid* instance);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
ADD_SCENE(hid, start, Start)
|
||||
ADD_SCENE(hid, main, Main)
|
||||
ADD_SCENE(hid, unpair, Unpair)
|
||||
ADD_SCENE(hid, exit_confirm, ExitConfirm)
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "../hid.h"
|
||||
#include "../views.h"
|
||||
|
||||
static void hid_scene_exit_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
if(result == DialogExResultLeft) {
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
} else if(result == DialogExResultRight) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
} else if(result == DialogExResultCenter) {
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, HidSceneMain);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewSubmenu);
|
||||
}
|
||||
}
|
||||
|
||||
void hid_scene_exit_confirm_on_enter(void* context) {
|
||||
Hid* app = context;
|
||||
|
||||
// Exit dialog view
|
||||
dialog_ex_reset(app->dialog);
|
||||
dialog_ex_set_result_callback(app->dialog, hid_scene_exit_confirm_dialog_callback);
|
||||
dialog_ex_set_context(app->dialog, app);
|
||||
dialog_ex_set_left_button_text(app->dialog, "Exit");
|
||||
dialog_ex_set_right_button_text(app->dialog, "Stay");
|
||||
dialog_ex_set_center_button_text(app->dialog, "Menu");
|
||||
dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewDialog);
|
||||
}
|
||||
|
||||
bool hid_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
Hid* app = context;
|
||||
bool consumed = false;
|
||||
UNUSED(app);
|
||||
UNUSED(event);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void hid_scene_exit_confirm_on_exit(void* context) {
|
||||
Hid* app = context;
|
||||
|
||||
dialog_ex_reset(app->dialog);
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
void hid_scene_main_on_enter(void* context) {
|
||||
Hid* app = context;
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id);
|
||||
view_dispatcher_switch_to_view(
|
||||
app->view_dispatcher, scene_manager_get_scene_state(app->scene_manager, HidSceneMain));
|
||||
}
|
||||
|
||||
bool hid_scene_main_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
157
applications/system/hid_app/scenes/hid_scene_start.c
Normal file
157
applications/system/hid_app/scenes/hid_scene_start.c
Normal file
@@ -0,0 +1,157 @@
|
||||
#include "../hid.h"
|
||||
#include "../views.h"
|
||||
|
||||
enum HidSubmenuIndex {
|
||||
HidSubmenuIndexKeynote,
|
||||
HidSubmenuIndexKeynoteVertical,
|
||||
HidSubmenuIndexKeyboard,
|
||||
HidSubmenuIndexNumpad,
|
||||
HidSubmenuIndexMedia,
|
||||
HidSubmenuIndexMusicMacOs,
|
||||
HidSubmenuIndexMovie,
|
||||
HidSubmenuIndexTikTok,
|
||||
HidSubmenuIndexMouse,
|
||||
HidSubmenuIndexMouseClicker,
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
HidSubmenuIndexPushToTalk,
|
||||
HidSubmenuIndexRemovePairing,
|
||||
};
|
||||
|
||||
static void hid_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
Hid* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void hid_scene_start_on_enter(void* context) {
|
||||
Hid* app = context;
|
||||
submenu_add_item(
|
||||
app->submenu, "Keynote", HidSubmenuIndexKeynote, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Keynote Vertical",
|
||||
HidSubmenuIndexKeynoteVertical,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Numpad", HidSubmenuIndexNumpad, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Media", HidSubmenuIndexMedia, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Apple Music macOS",
|
||||
HidSubmenuIndexMusicMacOs,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Movie", HidSubmenuIndexMovie, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Mouse", HidSubmenuIndexMouse, hid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"TikTok / YT Shorts",
|
||||
HidSubmenuIndexTikTok,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Mouse Clicker",
|
||||
HidSubmenuIndexMouseClicker,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Mouse Jiggler",
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"PushToTalk",
|
||||
HidSubmenuIndexPushToTalk,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Bluetooth Unpairing",
|
||||
HidSubmenuIndexRemovePairing,
|
||||
hid_scene_start_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
|
||||
submenu_set_selected_item(
|
||||
app->submenu, scene_manager_get_scene_state(app->scene_manager, HidSceneStart));
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewSubmenu);
|
||||
}
|
||||
|
||||
bool hid_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
Hid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == HidSubmenuIndexRemovePairing) {
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneUnpair);
|
||||
} else {
|
||||
HidView view_id;
|
||||
|
||||
switch(event.event) {
|
||||
case HidSubmenuIndexKeynote:
|
||||
view_id = HidViewKeynote;
|
||||
hid_keynote_set_orientation(app->hid_keynote, false);
|
||||
break;
|
||||
case HidSubmenuIndexKeynoteVertical:
|
||||
view_id = HidViewKeynote;
|
||||
hid_keynote_set_orientation(app->hid_keynote, true);
|
||||
break;
|
||||
case HidSubmenuIndexKeyboard:
|
||||
view_id = HidViewKeyboard;
|
||||
break;
|
||||
case HidSubmenuIndexNumpad:
|
||||
view_id = HidViewNumpad;
|
||||
break;
|
||||
case HidSubmenuIndexMedia:
|
||||
view_id = HidViewMedia;
|
||||
break;
|
||||
case HidSubmenuIndexMusicMacOs:
|
||||
view_id = HidViewMusicMacOs;
|
||||
break;
|
||||
case HidSubmenuIndexMovie:
|
||||
view_id = HidViewMovie;
|
||||
break;
|
||||
case HidSubmenuIndexTikTok:
|
||||
view_id = BtHidViewTikTok;
|
||||
break;
|
||||
case HidSubmenuIndexMouse:
|
||||
view_id = HidViewMouse;
|
||||
break;
|
||||
case HidSubmenuIndexMouseClicker:
|
||||
view_id = HidViewMouseClicker;
|
||||
break;
|
||||
case HidSubmenuIndexMouseJiggler:
|
||||
view_id = HidViewMouseJiggler;
|
||||
break;
|
||||
case HidSubmenuIndexPushToTalk:
|
||||
view_id = HidViewPushToTalkMenu;
|
||||
break;
|
||||
default:
|
||||
furi_crash();
|
||||
}
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, HidSceneMain, view_id);
|
||||
scene_manager_next_scene(app->scene_manager, HidSceneMain);
|
||||
}
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, HidSceneStart, event.event);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void hid_scene_start_on_exit(void* context) {
|
||||
Hid* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
@@ -29,9 +29,7 @@ void hid_scene_unpair_on_enter(void* context) {
|
||||
dialog_ex_reset(app->dialog);
|
||||
dialog_ex_set_result_callback(app->dialog, hid_scene_unpair_dialog_callback);
|
||||
dialog_ex_set_context(app->dialog, app);
|
||||
dialog_ex_set_header(app->dialog, "Unpair All Devices?", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(
|
||||
app->dialog, "All previous pairings\nwill be lost!", 64, 22, AlignCenter, AlignTop);
|
||||
dialog_ex_set_header(app->dialog, "Unpair the Device?", 64, 3, AlignCenter, AlignTop);
|
||||
dialog_ex_set_left_button_text(app->dialog, "Back");
|
||||
dialog_ex_set_right_button_text(app->dialog, "Unpair");
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ typedef struct {
|
||||
bool ok_pressed;
|
||||
bool back_pressed;
|
||||
bool connected;
|
||||
HidTransport transport;
|
||||
} HidKeyboardModel;
|
||||
|
||||
typedef struct {
|
||||
@@ -230,7 +229,8 @@ static void hid_keyboard_draw_callback(Canvas* canvas, void* context) {
|
||||
HidKeyboardModel* model = context;
|
||||
|
||||
// Header
|
||||
if((!model->connected) && (model->transport == HidTransportBle)) {
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(!model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keyboard");
|
||||
@@ -243,6 +243,7 @@ static void hid_keyboard_draw_callback(Canvas* canvas, void* context) {
|
||||
canvas, 4, 60, AlignLeft, AlignBottom, "Waiting for Connection...");
|
||||
return; // Dont render the keyboard if we are not yet connected
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
// Start shifting the all keys up if on the next row (Scrolling)
|
||||
@@ -400,13 +401,7 @@ HidKeyboard* hid_keyboard_alloc(Hid* bt_hid) {
|
||||
view_set_input_callback(hid_keyboard->view, hid_keyboard_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_keyboard->view,
|
||||
HidKeyboardModel * model,
|
||||
{
|
||||
model->transport = bt_hid->transport;
|
||||
model->y = 1;
|
||||
},
|
||||
true);
|
||||
hid_keyboard->view, HidKeyboardModel * model, { model->y = 1; }, true);
|
||||
|
||||
return hid_keyboard;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ typedef struct {
|
||||
bool ok_pressed;
|
||||
bool back_pressed;
|
||||
bool connected;
|
||||
HidTransport transport;
|
||||
} HidKeynoteModel;
|
||||
|
||||
static void hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
|
||||
@@ -40,13 +39,13 @@ static void hid_keynote_draw_callback(Canvas* canvas, void* context) {
|
||||
HidKeynoteModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keynote");
|
||||
@@ -92,12 +91,12 @@ static void hid_keynote_draw_callback(Canvas* canvas, void* context) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Ok
|
||||
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
|
||||
canvas_draw_icon(canvas, 63, 24, &I_Space_65x18);
|
||||
if(model->ok_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
|
||||
elements_slightly_rounded_box(canvas, 66, 26, 60, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
|
||||
canvas_draw_icon(canvas, 74, 28, &I_Ok_btn_9x9);
|
||||
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Space");
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
@@ -116,18 +115,18 @@ static void hid_keynote_draw_vertical_callback(Canvas* canvas, void* context) {
|
||||
HidKeynoteModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Keynote");
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Keynote");
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Keynote");
|
||||
#else
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Keynote");
|
||||
#endif
|
||||
|
||||
canvas_draw_icon(canvas, 2, 18, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
@@ -274,10 +273,6 @@ HidKeynote* hid_keynote_alloc(Hid* hid) {
|
||||
view_allocate_model(hid_keynote->view, ViewModelTypeLocking, sizeof(HidKeynoteModel));
|
||||
view_set_draw_callback(hid_keynote->view, hid_keynote_draw_callback);
|
||||
view_set_input_callback(hid_keynote->view, hid_keynote_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_keynote->view, HidKeynoteModel * model, { model->transport = hid->transport; }, true);
|
||||
|
||||
return hid_keynote;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ typedef struct {
|
||||
bool ok_pressed;
|
||||
bool connected;
|
||||
bool back_pressed;
|
||||
HidTransport transport;
|
||||
} HidMediaModel;
|
||||
|
||||
static void hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
|
||||
@@ -43,13 +42,13 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMediaModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Media");
|
||||
@@ -60,9 +59,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 79, 9, &I_Volup_8x6);
|
||||
@@ -70,9 +69,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 41, &I_Voldwn_6x6);
|
||||
@@ -80,9 +79,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_media_draw_arrow(canvas, 67, 28, CanvasDirectionRightToLeft);
|
||||
@@ -92,9 +91,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_media_draw_arrow(canvas, 96, 28, CanvasDirectionLeftToRight);
|
||||
@@ -104,9 +103,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_media_draw_arrow(canvas, 80, 28, CanvasDirectionLeftToRight);
|
||||
@@ -116,9 +115,9 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Exit
|
||||
if(model->back_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 111, 38, &I_Pin_back_arrow_10x10);
|
||||
@@ -209,10 +208,6 @@ HidMedia* hid_media_alloc(Hid* hid) {
|
||||
view_allocate_model(hid_media->view, ViewModelTypeLocking, sizeof(HidMediaModel));
|
||||
view_set_draw_callback(hid_media->view, hid_media_draw_callback);
|
||||
view_set_input_callback(hid_media->view, hid_media_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_media->view, HidMediaModel * model, { model->transport = hid->transport; }, true);
|
||||
|
||||
return hid_media;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct Hid Hid;
|
||||
|
||||
typedef struct HidMedia HidMedia;
|
||||
|
||||
HidMedia* hid_media_alloc(Hid* hid);
|
||||
|
||||
@@ -21,7 +21,6 @@ typedef struct {
|
||||
bool right_mouse_pressed;
|
||||
bool connected;
|
||||
uint8_t acceleration;
|
||||
HidTransport transport;
|
||||
} HidMouseModel;
|
||||
|
||||
static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
@@ -29,13 +28,13 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMouseModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse");
|
||||
@@ -54,9 +53,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 8, &I_Pin_arrow_up_7x9);
|
||||
@@ -64,9 +63,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 40, &I_Pin_arrow_down_7x9);
|
||||
@@ -74,9 +73,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 63, 25, &I_Pin_arrow_left_9x7);
|
||||
@@ -84,9 +83,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 95, 25, &I_Pin_arrow_right_9x7);
|
||||
@@ -94,9 +93,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Ok
|
||||
if(model->left_mouse_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 79, 24, &I_Left_mouse_icon_9x9);
|
||||
@@ -104,9 +103,9 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Back
|
||||
if(model->right_mouse_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 112, 38, &I_Right_mouse_icon_9x9);
|
||||
@@ -202,6 +201,15 @@ static bool hid_mouse_input_callback(InputEvent* event, void* context) {
|
||||
|
||||
if(event->type == InputTypeLong && event->key == InputKeyBack) {
|
||||
hid_hal_mouse_release_all(hid_mouse->hid);
|
||||
|
||||
with_view_model(
|
||||
hid_mouse->view,
|
||||
HidMouseModel * model,
|
||||
{
|
||||
model->left_mouse_held = false;
|
||||
model->left_mouse_pressed = false;
|
||||
},
|
||||
false);
|
||||
} else {
|
||||
hid_mouse_process(hid_mouse, event);
|
||||
consumed = true;
|
||||
@@ -218,10 +226,6 @@ HidMouse* hid_mouse_alloc(Hid* hid) {
|
||||
view_allocate_model(hid_mouse->view, ViewModelTypeLocking, sizeof(HidMouseModel));
|
||||
view_set_draw_callback(hid_mouse->view, hid_mouse_draw_callback);
|
||||
view_set_input_callback(hid_mouse->view, hid_mouse_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_mouse->view, HidMouseModel * model, { model->transport = hid->transport; }, true);
|
||||
|
||||
return hid_mouse;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ typedef struct {
|
||||
bool connected;
|
||||
bool running;
|
||||
int rate;
|
||||
HidTransport transport;
|
||||
} HidMouseClickerModel;
|
||||
|
||||
static void hid_mouse_clicker_start_or_restart_timer(void* context) {
|
||||
@@ -44,46 +43,46 @@ static void hid_mouse_clicker_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMouseClickerModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Clicker");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
// Ok
|
||||
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
|
||||
canvas_draw_icon(canvas, 58, 25, &I_Space_65x18);
|
||||
|
||||
if(model->running) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
FuriString* rate_label = furi_string_alloc();
|
||||
furi_string_printf(rate_label, "%d clicks/s\n\nUp / Down", model->rate);
|
||||
elements_multiline_text(canvas, AlignLeft, 35, furi_string_get_cstr(rate_label));
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
furi_string_free(rate_label);
|
||||
|
||||
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
|
||||
elements_slightly_rounded_box(canvas, 61, 27, 60, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text(canvas, AlignLeft, 35, "Press Start\nto start\nclicking");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
|
||||
|
||||
canvas_draw_icon(canvas, 69, 29, &I_Ok_btn_9x9);
|
||||
|
||||
if(model->running) {
|
||||
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Stop");
|
||||
elements_multiline_text_aligned(canvas, 86, 37, AlignLeft, AlignBottom, "Stop");
|
||||
} else {
|
||||
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Start");
|
||||
elements_multiline_text_aligned(canvas, 86, 37, AlignLeft, AlignBottom, "Start");
|
||||
}
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Clicks/s
|
||||
char label[20];
|
||||
snprintf(label, sizeof(label), "%d clicks/s", model->rate);
|
||||
elements_multiline_text_aligned(canvas, 28, 37, AlignCenter, AlignBottom, label);
|
||||
|
||||
canvas_draw_icon(canvas, 25, 20, &I_ButtonUp_7x4);
|
||||
canvas_draw_icon(canvas, 25, 44, &I_ButtonDown_7x4);
|
||||
|
||||
// Back
|
||||
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
|
||||
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Quit");
|
||||
canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8);
|
||||
elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Exit");
|
||||
}
|
||||
|
||||
static void hid_mouse_clicker_timer_callback(void* context) {
|
||||
@@ -145,6 +144,9 @@ static bool hid_mouse_clicker_input_callback(InputEvent* event, void* context) {
|
||||
rate_changed = true;
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
model->running = false;
|
||||
break;
|
||||
default:
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -179,10 +181,7 @@ HidMouseClicker* hid_mouse_clicker_alloc(Hid* hid) {
|
||||
with_view_model(
|
||||
hid_mouse_clicker->view,
|
||||
HidMouseClickerModel * model,
|
||||
{
|
||||
model->transport = hid->transport;
|
||||
model->rate = DEFAULT_CLICK_RATE;
|
||||
},
|
||||
{ model->rate = DEFAULT_CLICK_RATE; },
|
||||
true);
|
||||
|
||||
return hid_mouse_clicker;
|
||||
|
||||
@@ -17,7 +17,6 @@ typedef struct {
|
||||
bool running;
|
||||
int interval_idx;
|
||||
uint8_t counter;
|
||||
HidTransport transport;
|
||||
} HidMouseJigglerModel;
|
||||
|
||||
const int intervals[6] = {500, 2000, 5000, 10000, 30000, 60000};
|
||||
@@ -27,13 +26,13 @@ static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMouseJigglerModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 2, AlignLeft, AlignTop, "Mouse Jiggler");
|
||||
@@ -146,13 +145,7 @@ HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* hid) {
|
||||
hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler);
|
||||
|
||||
with_view_model(
|
||||
hid_mouse_jiggler->view,
|
||||
HidMouseJigglerModel * model,
|
||||
{
|
||||
model->transport = hid->transport;
|
||||
model->interval_idx = 2;
|
||||
},
|
||||
true);
|
||||
hid_mouse_jiggler->view, HidMouseJigglerModel * model, { model->interval_idx = 2; }, true);
|
||||
|
||||
return hid_mouse_jiggler;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ typedef struct {
|
||||
bool ok_pressed;
|
||||
bool connected;
|
||||
bool back_pressed;
|
||||
HidTransport transport;
|
||||
} HidMovieModel;
|
||||
|
||||
static void hid_movie_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
|
||||
@@ -43,13 +42,13 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMovieModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Movie");
|
||||
@@ -60,9 +59,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 79, 9, &I_Volup_8x6);
|
||||
@@ -70,9 +69,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 41, &I_Voldwn_6x6);
|
||||
@@ -80,9 +79,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_movie_draw_arrow(canvas, 65, 28, CanvasDirectionRightToLeft);
|
||||
@@ -91,9 +90,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_movie_draw_arrow(canvas, 96, 28, CanvasDirectionLeftToRight);
|
||||
@@ -102,9 +101,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_movie_draw_arrow(canvas, 80, 28, CanvasDirectionLeftToRight);
|
||||
@@ -114,9 +113,9 @@ static void hid_movie_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Exit
|
||||
if(model->back_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 111, 38, &I_Pin_back_arrow_10x10);
|
||||
@@ -211,9 +210,6 @@ HidMovie* hid_movie_alloc(Hid* hid) {
|
||||
view_set_draw_callback(hid_movie->view, hid_movie_draw_callback);
|
||||
view_set_input_callback(hid_movie->view, hid_movie_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_movie->view, HidMovieModel * model, { model->transport = hid->transport; }, true);
|
||||
|
||||
return hid_movie;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ typedef struct {
|
||||
bool ok_pressed;
|
||||
bool connected;
|
||||
bool back_pressed;
|
||||
HidTransport transport;
|
||||
} HidMusicMacosModel;
|
||||
|
||||
static void hid_music_macos_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) {
|
||||
@@ -43,13 +42,13 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
HidMusicMacosModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Music");
|
||||
@@ -60,9 +59,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 79, 9, &I_Volup_8x6);
|
||||
@@ -70,9 +69,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 41, &I_Voldwn_6x6);
|
||||
@@ -80,9 +79,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_music_macos_draw_arrow(canvas, 67, 28, CanvasDirectionRightToLeft);
|
||||
@@ -92,9 +91,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_music_macos_draw_arrow(canvas, 96, 28, CanvasDirectionLeftToRight);
|
||||
@@ -104,9 +103,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
hid_music_macos_draw_arrow(canvas, 80, 28, CanvasDirectionLeftToRight);
|
||||
@@ -116,9 +115,9 @@ static void hid_music_macos_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Exit
|
||||
if(model->back_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 111, 38, &I_Pin_back_arrow_10x10);
|
||||
@@ -215,12 +214,6 @@ HidMusicMacos* hid_music_macos_alloc(Hid* hid) {
|
||||
view_set_draw_callback(hid_music_macos->view, hid_music_macos_draw_callback);
|
||||
view_set_input_callback(hid_music_macos->view, hid_music_macos_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_music_macos->view,
|
||||
HidMusicMacosModel * model,
|
||||
{ model->transport = hid->transport; },
|
||||
true);
|
||||
|
||||
return hid_music_macos;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ typedef struct {
|
||||
bool back_pressed;
|
||||
bool connected;
|
||||
char key_string[5];
|
||||
HidTransport transport;
|
||||
} HidNumpadModel;
|
||||
|
||||
typedef struct {
|
||||
@@ -135,27 +134,28 @@ static void hid_numpad_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Header
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 7, 60, AlignLeft, AlignBottom, "Waiting for\nConnection...");
|
||||
}
|
||||
elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Numpad");
|
||||
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Numpad");
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
elements_multiline_text_aligned(
|
||||
canvas, 7, 60, AlignLeft, AlignBottom, "Waiting for\nConnection...");
|
||||
}
|
||||
elements_multiline_text_aligned(canvas, 20, 3, AlignLeft, AlignTop, "Numpad");
|
||||
#else
|
||||
elements_multiline_text_aligned(canvas, 12, 3, AlignLeft, AlignTop, "Numpad");
|
||||
#endif
|
||||
|
||||
canvas_draw_icon(canvas, 3, 18, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 15, 19, AlignLeft, AlignTop, "Hold to exit");
|
||||
|
||||
if(!model->connected && (model->transport == HidTransportBle)) {
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(!model->connected) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
uint8_t initY = 0; // = model->y == 0 ? 0 : 1;
|
||||
@@ -289,13 +289,7 @@ HidNumpad* hid_numpad_alloc(Hid* bt_hid) {
|
||||
view_set_input_callback(hid_numpad->view, hid_numpad_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_numpad->view,
|
||||
HidNumpadModel * model,
|
||||
{
|
||||
model->transport = bt_hid->transport;
|
||||
model->y = 0;
|
||||
},
|
||||
true);
|
||||
hid_numpad->view, HidNumpadModel * model, { model->y = 0; }, true);
|
||||
|
||||
return hid_numpad;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ typedef struct {
|
||||
size_t osIndex;
|
||||
size_t appIndex;
|
||||
size_t window_position;
|
||||
HidTransport transport;
|
||||
PushToTalkActionCallback callback_trigger_mute;
|
||||
PushToTalkActionCallback callback_trigger_camera;
|
||||
PushToTalkActionCallback callback_trigger_hand;
|
||||
@@ -575,13 +574,13 @@ static void hid_ptt_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Header
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
// OS and App labels
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
@@ -816,7 +815,6 @@ HidPushToTalk* hid_ptt_alloc(Hid* hid) {
|
||||
hid_ptt->view,
|
||||
HidPushToTalkModel * model,
|
||||
{
|
||||
model->transport = hid->transport;
|
||||
model->muted = true; // assume we're muted
|
||||
model->os = furi_string_alloc();
|
||||
model->app = furi_string_alloc();
|
||||
|
||||
@@ -20,7 +20,6 @@ typedef struct {
|
||||
bool connected;
|
||||
bool is_cursor_set;
|
||||
bool back_mouse_pressed;
|
||||
HidTransport transport;
|
||||
} HidTikTokModel;
|
||||
|
||||
static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
@@ -28,13 +27,13 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
HidTikTokModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#ifdef HID_TRANSPORT_BLE
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
#endif
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "TikTok /");
|
||||
@@ -46,9 +45,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Pause
|
||||
if(model->back_mouse_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 107, 33, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 113, 37, &I_Pause_icon_9x9);
|
||||
@@ -56,9 +55,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 6, &I_S_UP_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 8, &I_Arr_up_7x9);
|
||||
@@ -66,9 +65,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 68, 36, &I_S_DOWN_31x15);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 80, 40, &I_Arr_dwn_7x9);
|
||||
@@ -76,9 +75,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 61, 13, &I_S_LEFT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 64, 25, &I_Voldwn_6x6);
|
||||
@@ -86,9 +85,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 91, 13, &I_S_RIGHT_15x31);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 95, 25, &I_Volup_8x6);
|
||||
@@ -96,9 +95,9 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_set_bitmap_mode(canvas, true);
|
||||
canvas_draw_icon(canvas, 74, 19, &I_Pressed_Button_19x19);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_bitmap_mode(canvas, false);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 78, 25, &I_Like_def_11x9);
|
||||
@@ -234,9 +233,6 @@ HidTikTok* hid_tiktok_alloc(Hid* bt_hid) {
|
||||
view_set_draw_callback(hid_tiktok->view, hid_tiktok_draw_callback);
|
||||
view_set_input_callback(hid_tiktok->view, hid_tiktok_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_tiktok->view, HidTikTokModel * model, { model->transport = bt_hid->transport; }, true);
|
||||
|
||||
return hid_tiktok;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,27 @@ App(
|
||||
fap_category="assets",
|
||||
)
|
||||
|
||||
App(
|
||||
appid="js_cli",
|
||||
targets=["f7"],
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_cli_plugin_ep",
|
||||
requires=["cli"],
|
||||
sources=[
|
||||
"*.c*",
|
||||
"!modules",
|
||||
"modules/js_flipper.c",
|
||||
],
|
||||
)
|
||||
|
||||
App(
|
||||
appid="js_app_start",
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="js_app_on_system_start",
|
||||
sources=["js_start.c"],
|
||||
order=160,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="js_dialog",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "js_app_i.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <assets_icons.h>
|
||||
#include <cli/cli.h>
|
||||
|
||||
#define TAG "JS app"
|
||||
|
||||
@@ -128,4 +129,90 @@ int32_t js_app(void* arg) {
|
||||
|
||||
js_app_free(app);
|
||||
return 0;
|
||||
} //-V773
|
||||
} //-V773
|
||||
|
||||
typedef struct {
|
||||
Cli* cli;
|
||||
FuriSemaphore* exit_sem;
|
||||
} JsCliContext;
|
||||
|
||||
static void js_cli_print(JsCliContext* ctx, const char* msg) {
|
||||
cli_write(ctx->cli, (uint8_t*)msg, strlen(msg));
|
||||
}
|
||||
|
||||
static void js_cli_exit(JsCliContext* ctx) {
|
||||
furi_check(furi_semaphore_release(ctx->exit_sem) == FuriStatusOk);
|
||||
}
|
||||
|
||||
static void js_cli_callback(JsThreadEvent event, const char* msg, void* context) {
|
||||
JsCliContext* ctx = context;
|
||||
switch(event) {
|
||||
case JsThreadEventError:
|
||||
js_cli_print(ctx, "---- ERROR ----\r\n");
|
||||
js_cli_print(ctx, msg);
|
||||
js_cli_print(ctx, "\r\n");
|
||||
break;
|
||||
case JsThreadEventErrorTrace:
|
||||
js_cli_print(ctx, "Trace:\r\n");
|
||||
js_cli_print(ctx, msg);
|
||||
js_cli_print(ctx, "\r\n");
|
||||
|
||||
js_cli_exit(ctx); // Exit when an error occurs
|
||||
break;
|
||||
case JsThreadEventPrint:
|
||||
js_cli_print(ctx, msg);
|
||||
js_cli_print(ctx, "\r\n");
|
||||
break;
|
||||
case JsThreadEventDone:
|
||||
js_cli_print(ctx, "Script done!\r\n");
|
||||
|
||||
js_cli_exit(ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void js_cli_execute(Cli* cli, FuriString* args, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
const char* path = furi_string_get_cstr(args);
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
do {
|
||||
if(furi_string_size(args) == 0) {
|
||||
printf("Usage:\r\njs <path>\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!storage_file_exists(storage, path)) {
|
||||
printf("Can not open file %s\r\n", path);
|
||||
break;
|
||||
}
|
||||
|
||||
JsCliContext ctx = {.cli = cli};
|
||||
ctx.exit_sem = furi_semaphore_alloc(1, 0);
|
||||
|
||||
printf("Running script %s, press CTRL+C to stop\r\n", path);
|
||||
JsThread* js_thread = js_thread_run(path, js_cli_callback, &ctx);
|
||||
|
||||
while(furi_semaphore_acquire(ctx.exit_sem, 100) != FuriStatusOk) {
|
||||
if(cli_cmd_interrupt_received(cli)) break;
|
||||
}
|
||||
|
||||
js_thread_stop(js_thread);
|
||||
furi_semaphore_free(ctx.exit_sem);
|
||||
} while(false);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
static const FlipperAppPluginDescriptor plugin_descriptor = {
|
||||
.appid = "js_cli",
|
||||
.ep_api_version = 1,
|
||||
.entry_point = &js_cli_execute,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* js_cli_plugin_ep(void) {
|
||||
return &plugin_descriptor;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#define TAG "JS modules"
|
||||
|
||||
// Absolute path is used to make possible plugin load from CLI
|
||||
#define MODULES_PATH "/ext/apps_data/js_app/plugins"
|
||||
|
||||
typedef struct {
|
||||
JsModeConstructor create;
|
||||
JsModeDestructor destroy;
|
||||
@@ -81,7 +84,7 @@ mjs_val_t js_module_require(JsModules* modules, const char* name, size_t name_le
|
||||
// External module load
|
||||
if(!module_found) {
|
||||
FuriString* module_path = furi_string_alloc();
|
||||
furi_string_printf(module_path, "%s/js_%s.fal", APP_DATA_PATH("plugins"), name);
|
||||
furi_string_printf(module_path, "%s/js_%s.fal", MODULES_PATH, name);
|
||||
FURI_LOG_I(TAG, "Loading external module %s", furi_string_get_cstr(module_path));
|
||||
do {
|
||||
uint32_t plugin_cnt_last = plugin_manager_get_count(modules->plugin_manager);
|
||||
|
||||
11
applications/system/js_app/js_start.c
Normal file
11
applications/system/js_app/js_start.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <cli/cli_i.h>
|
||||
|
||||
static void js_cli_execute_wrapper(Cli* cli, FuriString* args, void* context) {
|
||||
cli_plugin_wrapper("js_cli", 1, cli, args, context);
|
||||
}
|
||||
|
||||
void js_app_on_system_start(void) {
|
||||
Cli* cli = furi_record_open(RECORD_CLI);
|
||||
cli_add_command(cli, "js", CliCommandFlagDefault, js_cli_execute_wrapper, NULL);
|
||||
furi_record_close(RECORD_CLI);
|
||||
}
|
||||
@@ -45,12 +45,12 @@ static void js_print(struct mjs* mjs) {
|
||||
FuriString* msg_str = furi_string_alloc();
|
||||
js_str_print(msg_str, mjs);
|
||||
|
||||
printf("%s\r\n", furi_string_get_cstr(msg_str));
|
||||
|
||||
JsThread* worker = mjs_get_context(mjs);
|
||||
furi_assert(worker);
|
||||
if(worker->app_callback) {
|
||||
worker->app_callback(JsThreadEventPrint, furi_string_get_cstr(msg_str), worker->context);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "%s\r\n", furi_string_get_cstr(msg_str));
|
||||
}
|
||||
|
||||
furi_string_free(msg_str);
|
||||
|
||||
@@ -79,15 +79,7 @@ Up to 5 keys can be hold simultaneously.
|
||||
| HOLD | Special key or single character | Press and hold key until RELEASE command |
|
||||
| RELEASE | Special key or single character | Release key |
|
||||
|
||||
## Wait for button press
|
||||
|
||||
Will wait indefinitely for a button to be pressed
|
||||
| Command | Parameters | Notes |
|
||||
| --------------------- | ------------ | --------------------------------------------------------------------- |
|
||||
| WAIT_FOR_BUTTON_PRESS | None | Will wait for the user to press a button to continue script execution |
|
||||
|
||||
|
||||
### String
|
||||
## String
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
| ------- | ----------- | ----------------- |
|
||||
@@ -126,7 +118,54 @@ Send [SysRq command](https://en.wikipedia.org/wiki/Magic_SysRq_key)
|
||||
| ------- | ---------------- | ----- |
|
||||
| SYSRQ | Single character | |
|
||||
|
||||
### USB device ID
|
||||
## Media keys
|
||||
|
||||
Some Media/Consumer Control keys can be pressed with "MEDIA" command
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
| ------- | ------------------------- | ----- |
|
||||
| MEDIA | Media key, see list below | |
|
||||
|
||||
| Key name | Notes |
|
||||
| ----------------- | ----------------------------- |
|
||||
| POWER | |
|
||||
| REBOOT | |
|
||||
| SLEEP | |
|
||||
| LOGOFF | |
|
||||
| EXIT | |
|
||||
| HOME | |
|
||||
| BACK | |
|
||||
| FORWARD | |
|
||||
| REFRESH | |
|
||||
| SNAPSHOT | Take photo in a camera app |
|
||||
| PLAY | |
|
||||
| PAUSE | |
|
||||
| PLAY_PAUSE | |
|
||||
| NEXT_TRACK | |
|
||||
| PREV_TRACK | |
|
||||
| STOP | |
|
||||
| EJECT | |
|
||||
| MUTE | |
|
||||
| VOLUME_UP | |
|
||||
| VOLUME_DOWN | |
|
||||
| FN | Fn/Globe key on Mac keyboard |
|
||||
| BRIGHT_UP | Increase display brightness |
|
||||
| BRIGHT_DOWN | Decrease display brightness |
|
||||
|
||||
## Fn/Globe key commands (Mac/iPad)
|
||||
|
||||
| Command | Parameters | Notes |
|
||||
| ------- | ------------------------------- | ----- |
|
||||
| GLOBE | Special key or single character | |
|
||||
|
||||
## Wait for button press
|
||||
|
||||
Will wait indefinitely for a button to be pressed
|
||||
| Command | Parameters | Notes |
|
||||
| --------------------- | ------------ | --------------------------------------------------------------------- |
|
||||
| WAIT_FOR_BUTTON_PRESS | None | Will wait for the user to press a button to continue script execution |
|
||||
|
||||
## USB device ID
|
||||
|
||||
You can set the custom ID of the Flipper USB HID device. ID command should be in the **first line** of script, it is executed before script run.
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ static void flipper_print_version(const char* target, const Version* version) {
|
||||
#include <notification/notification_app.h>
|
||||
#include <dolphin/helpers/dolphin_state.h>
|
||||
#include <applications/main/u2f/u2f_data.h>
|
||||
#include <applications/main/infrared/infrared_app.h>
|
||||
#include <expansion/expansion_settings_filename.h>
|
||||
#include <applications/main/archive/helpers/archive_favorites.h>
|
||||
#include <momentum/namespoof.h>
|
||||
@@ -72,6 +73,7 @@ void flipper_migrate_files() {
|
||||
{INT_PATH(".bt.keys"), BT_KEYS_STORAGE_PATH, true},
|
||||
{INT_PATH(".expansion.settings"), EXPANSION_SETTINGS_PATH, true},
|
||||
{INT_PATH(".notification.settings"), NOTIFICATION_SETTINGS_PATH, true},
|
||||
{INT_PATH(".infrared.settings"), INFRARED_SETTINGS_PATH, true},
|
||||
// Ext -> Int
|
||||
{CFG_PATH("desktop.settings"), DESKTOP_SETTINGS_PATH, true},
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <infrared.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -225,7 +225,7 @@ static bool mf_desfire_poller_detect(NfcGenericEvent event, void* context) {
|
||||
bool protocol_detected = false;
|
||||
|
||||
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
|
||||
MfDesfireKeyVersion key_version = 0;
|
||||
MfDesfireKeyVersion key_version = {0};
|
||||
MfDesfireError error = mf_desfire_poller_read_key_version(instance, 0, &key_version);
|
||||
protocol_detected = (error == MfDesfireErrorNone);
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ MfDesfireError mf_desfire_poller_read_key_version(
|
||||
MfDesfirePoller* instance,
|
||||
uint8_t key_num,
|
||||
MfDesfireKeyVersion* data) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
furi_check(instance);
|
||||
furi_check(data);
|
||||
|
||||
bit_buffer_set_size_bytes(instance->input_buffer, sizeof(uint8_t) * 2);
|
||||
bit_buffer_set_byte(instance->input_buffer, 0, MF_DESFIRE_CMD_GET_KEY_VERSION);
|
||||
|
||||
@@ -13,7 +13,12 @@ typedef struct {
|
||||
uint32_t timestamp;
|
||||
} SavedStructHeader;
|
||||
|
||||
bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic, uint8_t version) {
|
||||
bool saved_struct_save(
|
||||
const char* path,
|
||||
const void* data,
|
||||
size_t size,
|
||||
uint8_t magic,
|
||||
uint8_t version) {
|
||||
furi_check(path);
|
||||
furi_check(data);
|
||||
furi_check(size);
|
||||
@@ -35,7 +40,7 @@ bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic,
|
||||
if(result) {
|
||||
// Calculate checksum
|
||||
uint8_t checksum = 0;
|
||||
uint8_t* source = data;
|
||||
const uint8_t* source = data;
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
checksum += source[i];
|
||||
}
|
||||
@@ -63,6 +68,10 @@ bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic,
|
||||
}
|
||||
|
||||
bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic, uint8_t version) {
|
||||
furi_check(path);
|
||||
furi_check(data);
|
||||
furi_check(size);
|
||||
|
||||
FURI_LOG_I(TAG, "Loading \"%s\"", path);
|
||||
|
||||
SavedStructHeader header;
|
||||
@@ -131,13 +140,12 @@ bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool saved_struct_get_payload_size(
|
||||
bool saved_struct_get_metadata(
|
||||
const char* path,
|
||||
uint8_t magic,
|
||||
uint8_t version,
|
||||
uint8_t* magic,
|
||||
uint8_t* version,
|
||||
size_t* payload_size) {
|
||||
furi_check(path);
|
||||
furi_check(payload_size);
|
||||
|
||||
SavedStructHeader header;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
@@ -151,26 +159,22 @@ bool saved_struct_get_payload_size(
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader));
|
||||
if(bytes_count != sizeof(SavedStructHeader)) {
|
||||
if(storage_file_read(file, &header, sizeof(SavedStructHeader)) !=
|
||||
sizeof(SavedStructHeader)) {
|
||||
FURI_LOG_E(TAG, "Failed to read header");
|
||||
break;
|
||||
}
|
||||
|
||||
if((header.magic != magic) || (header.version != version)) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Magic(%d != %d) or Version(%d != %d) mismatch of file \"%s\"",
|
||||
header.magic,
|
||||
magic,
|
||||
header.version,
|
||||
version,
|
||||
path);
|
||||
break;
|
||||
if(magic) {
|
||||
*magic = header.magic;
|
||||
}
|
||||
if(version) {
|
||||
*version = header.version;
|
||||
}
|
||||
if(payload_size) {
|
||||
uint64_t file_size = storage_file_size(file);
|
||||
*payload_size = file_size - sizeof(SavedStructHeader);
|
||||
}
|
||||
|
||||
uint64_t file_size = storage_file_size(file);
|
||||
*payload_size = file_size - sizeof(SavedStructHeader);
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
/**
|
||||
* @file saved_struct.h
|
||||
* @brief SavedStruct - data serialization/de-serialization
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -8,14 +13,50 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Load data from the file in saved structure format
|
||||
*
|
||||
* @param[in] path The path to the file
|
||||
* @param[out] data Pointer to the memory where to load data
|
||||
* @param[in] size The size of the data
|
||||
* @param[in] magic The magic to embed into metadata
|
||||
* @param[in] version The version to embed into metadata
|
||||
*
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic, uint8_t version);
|
||||
|
||||
bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic, uint8_t version);
|
||||
|
||||
bool saved_struct_get_payload_size(
|
||||
/** Save data in saved structure format
|
||||
*
|
||||
* @param[in] path The path to the file
|
||||
* @param[in] data Pointer to the memory where data
|
||||
* @param[in] size The size of the data
|
||||
* @param[in] magic The magic to embed into metadata
|
||||
* @param[in] version The version to embed into metadata
|
||||
*
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool saved_struct_save(
|
||||
const char* path,
|
||||
const void* data,
|
||||
size_t size,
|
||||
uint8_t magic,
|
||||
uint8_t version,
|
||||
uint8_t version);
|
||||
|
||||
/** Get SavedStructure file metadata
|
||||
*
|
||||
* @param[in] path The path to the file
|
||||
* @param[out] magic Pointer to store magic or NULL if you don't need it
|
||||
* @param[out] version Pointer to store version or NULL if you don't need
|
||||
* it
|
||||
* @param[out] payload_size Pointer to store payload size or NULL if you don't
|
||||
* need it
|
||||
*
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool saved_struct_get_metadata(
|
||||
const char* path,
|
||||
uint8_t* magic,
|
||||
uint8_t* version,
|
||||
size_t* payload_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,60.0,,
|
||||
Version,+,60.3,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@@ -1205,6 +1205,7 @@ Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
||||
Function,+,furi_hal_gpio_remove_int_callback,void,const GpioPin*
|
||||
Function,+,furi_hal_hid_consumer_key_press,_Bool,uint16_t
|
||||
Function,+,furi_hal_hid_consumer_key_release,_Bool,uint16_t
|
||||
Function,+,furi_hal_hid_consumer_key_release_all,_Bool,
|
||||
Function,+,furi_hal_hid_get_led_state,uint8_t,
|
||||
Function,+,furi_hal_hid_is_connected,_Bool,
|
||||
Function,+,furi_hal_hid_kb_press,_Bool,uint16_t
|
||||
@@ -2302,9 +2303,9 @@ Function,+,rpc_system_app_set_callback,void,"RpcAppSystem*, RpcAppSystemCallback
|
||||
Function,+,rpc_system_app_set_error_code,void,"RpcAppSystem*, uint32_t"
|
||||
Function,+,rpc_system_app_set_error_text,void,"RpcAppSystem*, const char*"
|
||||
Function,-,rpmatch,int,const char*
|
||||
Function,+,saved_struct_get_payload_size,_Bool,"const char*, uint8_t, uint8_t, size_t*"
|
||||
Function,+,saved_struct_get_metadata,_Bool,"const char*, uint8_t*, uint8_t*, size_t*"
|
||||
Function,+,saved_struct_load,_Bool,"const char*, void*, size_t, uint8_t, uint8_t"
|
||||
Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t"
|
||||
Function,+,saved_struct_save,_Bool,"const char*, const void*, size_t, uint8_t, uint8_t"
|
||||
Function,-,scalbln,double,"double, long int"
|
||||
Function,-,scalblnf,float,"float, long int"
|
||||
Function,-,scalblnl,long double,"long double, long"
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,60.0,,
|
||||
Version,+,60.3,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/main/archive/helpers/archive_helpers_ext.h,,
|
||||
Header,+,applications/main/subghz/subghz_fap.h,,
|
||||
@@ -784,7 +784,7 @@ Function,+,bt_profile_start,FuriHalBleProfileBase*,"Bt*, const FuriHalBleProfile
|
||||
Function,+,bt_remote_rssi,_Bool,"Bt*, uint8_t*"
|
||||
Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*"
|
||||
Function,-,bt_settings_load,_Bool,BtSettings*
|
||||
Function,+,bt_settings_save,_Bool,BtSettings*
|
||||
Function,+,bt_settings_save,_Bool,const BtSettings*
|
||||
Function,+,buffered_file_stream_alloc,Stream*,Storage*
|
||||
Function,+,buffered_file_stream_close,_Bool,Stream*
|
||||
Function,+,buffered_file_stream_get_error,FS_Error,Stream*
|
||||
@@ -1036,7 +1036,7 @@ Function,+,expansion_get_settings,ExpansionSettings*,Expansion*
|
||||
Function,+,expansion_is_connected,_Bool,Expansion*
|
||||
Function,+,expansion_set_listen_serial,void,"Expansion*, FuriHalSerialId"
|
||||
Function,-,expansion_settings_load,_Bool,ExpansionSettings*
|
||||
Function,+,expansion_settings_save,_Bool,ExpansionSettings*
|
||||
Function,+,expansion_settings_save,_Bool,const ExpansionSettings*
|
||||
Function,-,expf,float,float
|
||||
Function,-,expl,long double,long double
|
||||
Function,-,explicit_bzero,void,"void*, size_t"
|
||||
@@ -1358,6 +1358,7 @@ Function,+,furi_hal_gpio_init_simple,void,"const GpioPin*, const GpioMode"
|
||||
Function,+,furi_hal_gpio_remove_int_callback,void,const GpioPin*
|
||||
Function,+,furi_hal_hid_consumer_key_press,_Bool,uint16_t
|
||||
Function,+,furi_hal_hid_consumer_key_release,_Bool,uint16_t
|
||||
Function,+,furi_hal_hid_consumer_key_release_all,_Bool,
|
||||
Function,+,furi_hal_hid_get_led_state,uint8_t,
|
||||
Function,+,furi_hal_hid_is_connected,_Bool,
|
||||
Function,+,furi_hal_hid_kb_press,_Bool,uint16_t
|
||||
@@ -1408,12 +1409,9 @@ Function,+,furi_hal_infrared_async_tx_set_signal_sent_isr_callback,void,"FuriHal
|
||||
Function,+,furi_hal_infrared_async_tx_start,void,"uint32_t, float"
|
||||
Function,+,furi_hal_infrared_async_tx_stop,void,
|
||||
Function,+,furi_hal_infrared_async_tx_wait_termination,void,
|
||||
Function,+,furi_hal_infrared_get_debug_out_status,_Bool,
|
||||
Function,+,furi_hal_infrared_is_auto_detect_enabled,_Bool,
|
||||
Function,+,furi_hal_infrared_detect_tx_output,FuriHalInfraredTxPin,
|
||||
Function,+,furi_hal_infrared_is_busy,_Bool,
|
||||
Function,+,furi_hal_infrared_is_external_connected,_Bool,
|
||||
Function,+,furi_hal_infrared_set_auto_detect,void,_Bool
|
||||
Function,+,furi_hal_infrared_set_debug_out,void,_Bool
|
||||
Function,+,furi_hal_infrared_set_tx_output,void,FuriHalInfraredTxPin
|
||||
Function,-,furi_hal_init,void,
|
||||
Function,-,furi_hal_init_early,void,
|
||||
Function,-,furi_hal_interrupt_init,void,
|
||||
@@ -3006,9 +3004,9 @@ Function,+,rpc_system_app_set_error_code,void,"RpcAppSystem*, uint32_t"
|
||||
Function,+,rpc_system_app_set_error_text,void,"RpcAppSystem*, const char*"
|
||||
Function,-,rpmatch,int,const char*
|
||||
Function,-,run_with_default_app,void,const char*
|
||||
Function,+,saved_struct_get_payload_size,_Bool,"const char*, uint8_t, uint8_t, size_t*"
|
||||
Function,+,saved_struct_get_metadata,_Bool,"const char*, uint8_t*, uint8_t*, size_t*"
|
||||
Function,+,saved_struct_load,_Bool,"const char*, void*, size_t, uint8_t, uint8_t"
|
||||
Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t"
|
||||
Function,+,saved_struct_save,_Bool,"const char*, const void*, size_t, uint8_t, uint8_t"
|
||||
Function,-,scalbln,double,"double, long int"
|
||||
Function,-,scalblnf,float,"float, long int"
|
||||
Function,-,scalblnl,long double,"long double, long"
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_cortex.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
@@ -76,11 +76,15 @@ typedef enum {
|
||||
InfraredStateMAX,
|
||||
} InfraredState;
|
||||
|
||||
static FuriHalInfraredTxPin infrared_tx_output = FuriHalInfraredTxPinInternal;
|
||||
static volatile InfraredState furi_hal_infrared_state = InfraredStateIdle;
|
||||
static InfraredTimTx infrared_tim_tx;
|
||||
static InfraredTimRx infrared_tim_rx;
|
||||
static bool infrared_external_output;
|
||||
static bool auto_detect;
|
||||
|
||||
static const GpioPin* infrared_tx_pins[FuriHalInfraredTxPinMax] = {
|
||||
[FuriHalInfraredTxPinInternal] = &gpio_infrared_tx,
|
||||
[FuriHalInfraredTxPinExtPA7] = &gpio_ext_pa7,
|
||||
};
|
||||
|
||||
static void furi_hal_infrared_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_shift);
|
||||
static void furi_hal_infrared_async_tx_free_resources(void);
|
||||
@@ -91,14 +95,6 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void);
|
||||
static void furi_hal_infrared_tx_dma_polarity_isr();
|
||||
static void furi_hal_infrared_tx_dma_isr();
|
||||
|
||||
void furi_hal_infrared_set_debug_out(bool enable) {
|
||||
infrared_external_output = enable;
|
||||
}
|
||||
|
||||
bool furi_hal_infrared_get_debug_out_status(void) {
|
||||
return infrared_external_output;
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tim_rx_isr(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
@@ -357,18 +353,8 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
|
||||
LL_TIM_SetAutoReload(
|
||||
INFRARED_DMA_TIMER,
|
||||
__LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(INFRARED_DMA_TIMER), freq));
|
||||
if(infrared_external_output) {
|
||||
LL_TIM_OC_SetCompareCH1(
|
||||
INFRARED_DMA_TIMER,
|
||||
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
/* LL_TIM_OCMODE_PWM2 set by DMA */
|
||||
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N);
|
||||
LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER);
|
||||
} else {
|
||||
|
||||
if(infrared_tx_output == FuriHalInfraredTxPinInternal) {
|
||||
LL_TIM_OC_SetCompareCH3(
|
||||
INFRARED_DMA_TIMER,
|
||||
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
|
||||
@@ -379,7 +365,19 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
|
||||
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N);
|
||||
LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER);
|
||||
} else if(infrared_tx_output == FuriHalInfraredTxPinExtPA7) {
|
||||
LL_TIM_OC_SetCompareCH1(
|
||||
INFRARED_DMA_TIMER,
|
||||
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
|
||||
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
/* LL_TIM_OCMODE_PWM2 set by DMA */
|
||||
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
|
||||
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
|
||||
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
|
||||
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N);
|
||||
LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER);
|
||||
}
|
||||
|
||||
LL_TIM_DisableMasterSlaveMode(INFRARED_DMA_TIMER);
|
||||
LL_TIM_EnableAllOutputs(INFRARED_DMA_TIMER);
|
||||
LL_TIM_DisableIT_UPDATE(INFRARED_DMA_TIMER);
|
||||
@@ -388,11 +386,13 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
|
||||
|
||||
static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
if(infrared_external_output) {
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1);
|
||||
} else {
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2);
|
||||
|
||||
if(infrared_tx_output == FuriHalInfraredTxPinInternal) {
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t)(&(INFRARED_DMA_TIMER->CCMR2));
|
||||
} else if(infrared_tx_output == FuriHalInfraredTxPinExtPA7) {
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t)(&(INFRARED_DMA_TIMER->CCMR1));
|
||||
}
|
||||
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||
@@ -589,11 +589,8 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
|
||||
(furi_hal_infrared_state == InfraredStateIdle) ||
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopped));
|
||||
|
||||
if(infrared_external_output) {
|
||||
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
} else {
|
||||
furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
}
|
||||
furi_hal_gpio_init(
|
||||
infrared_tx_pins[infrared_tx_output], GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_interrupt_set_isr(INFRARED_DMA_CH1_IRQ, NULL, NULL);
|
||||
furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, NULL, NULL);
|
||||
|
||||
@@ -655,37 +652,10 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
|
||||
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* DMA -> TIMx_RCR */
|
||||
furi_delay_us(5);
|
||||
|
||||
if(auto_detect) {
|
||||
infrared_external_output = furi_hal_infrared_is_external_connected();
|
||||
if(infrared_external_output) {
|
||||
if(!furi_hal_power_is_otg_enabled()) {
|
||||
uint8_t attempts = 0;
|
||||
while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
|
||||
furi_hal_power_enable_otg();
|
||||
furi_delay_ms(10);
|
||||
}
|
||||
}
|
||||
} else if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
}
|
||||
|
||||
if(infrared_external_output) {
|
||||
LL_GPIO_ResetOutputPin(
|
||||
gpio_ext_pa7.port, gpio_ext_pa7.pin); /* when disable it prevents false pulse */
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pa7, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
|
||||
} else {
|
||||
LL_GPIO_ResetOutputPin(
|
||||
gpio_infrared_tx.port,
|
||||
gpio_infrared_tx.pin); /* when disable it prevents false pulse */
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_infrared_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedHigh,
|
||||
GpioAltFn1TIM1);
|
||||
}
|
||||
const GpioPin* tx_gpio = infrared_tx_pins[infrared_tx_output];
|
||||
LL_GPIO_ResetOutputPin(tx_gpio->port, tx_gpio->pin); /* when disable it prevents false pulse */
|
||||
furi_hal_gpio_init_ex(
|
||||
tx_gpio, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedHigh, GpioAltFn1TIM1);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */
|
||||
@@ -731,18 +701,22 @@ void furi_hal_infrared_async_tx_set_signal_sent_isr_callback(
|
||||
infrared_tim_tx.signal_sent_context = context;
|
||||
}
|
||||
|
||||
bool furi_hal_infrared_is_external_connected(void) {
|
||||
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeInput, GpioPullUp, GpioSpeedHigh);
|
||||
furi_delay_ms(1);
|
||||
bool is_external_connected = !furi_hal_gpio_read(&gpio_ext_pa7);
|
||||
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
return is_external_connected;
|
||||
FuriHalInfraredTxPin furi_hal_infrared_detect_tx_output(void) {
|
||||
for(FuriHalInfraredTxPin pin = FuriHalInfraredTxPinInternal + 1; //-V1008
|
||||
pin < FuriHalInfraredTxPinMax;
|
||||
++pin) {
|
||||
const GpioPin* gpio = infrared_tx_pins[pin];
|
||||
furi_hal_gpio_init(gpio, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
furi_hal_cortex_delay_us(1000U);
|
||||
const bool level = furi_hal_gpio_read(gpio);
|
||||
furi_hal_gpio_init(gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
if(!level) return pin;
|
||||
}
|
||||
|
||||
return FuriHalInfraredTxPinInternal;
|
||||
}
|
||||
|
||||
void furi_hal_infrared_set_auto_detect(bool enable) {
|
||||
auto_detect = enable;
|
||||
void furi_hal_infrared_set_tx_output(FuriHalInfraredTxPin tx_pin) {
|
||||
furi_check(tx_pin < FuriHalInfraredTxPinMax);
|
||||
infrared_tx_output = tx_pin;
|
||||
}
|
||||
|
||||
bool furi_hal_infrared_is_auto_detect_enabled(void) {
|
||||
return auto_detect;
|
||||
}
|
||||
@@ -351,6 +351,13 @@ bool furi_hal_hid_consumer_key_release(uint16_t button) {
|
||||
return hid_send_report(ReportIdConsumer);
|
||||
}
|
||||
|
||||
bool furi_hal_hid_consumer_key_release_all(void) {
|
||||
for(uint8_t key_nb = 0; key_nb < HID_CONSUMER_MAX_KEYS; key_nb++) {
|
||||
hid_report.consumer.btn[key_nb] = 0;
|
||||
}
|
||||
return hid_send_report(ReportIdConsumer);
|
||||
}
|
||||
|
||||
static void* hid_set_string_descr(char* str) {
|
||||
furi_assert(str);
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ extern "C" {
|
||||
#define INFRARED_MAX_FREQUENCY 56000
|
||||
#define INFRARED_MIN_FREQUENCY 10000
|
||||
|
||||
typedef enum {
|
||||
FuriHalInfraredTxPinInternal,
|
||||
FuriHalInfraredTxPinExtPA7,
|
||||
FuriHalInfraredTxPinMax,
|
||||
} FuriHalInfraredTxPin;
|
||||
|
||||
typedef enum {
|
||||
FuriHalInfraredTxGetDataStateOk, /**< New data obtained */
|
||||
FuriHalInfraredTxGetDataStateDone, /**< New data obtained, and this is end of package */
|
||||
@@ -48,12 +54,6 @@ typedef void (*FuriHalInfraredRxCaptureCallback)(void* ctx, bool level, uint32_t
|
||||
*/
|
||||
typedef void (*FuriHalInfraredRxTimeoutCallback)(void* ctx);
|
||||
|
||||
// Debug TX pin set
|
||||
void furi_hal_infrared_set_debug_out(bool enable);
|
||||
|
||||
// Debug TX pin get status
|
||||
bool furi_hal_infrared_get_debug_out_status(void);
|
||||
|
||||
/** Initialize INFRARED RX timer to receive interrupts.
|
||||
*
|
||||
* It provides interrupts for every RX-signal edge changing with its duration.
|
||||
@@ -149,23 +149,28 @@ void furi_hal_infrared_async_tx_set_signal_sent_isr_callback(
|
||||
FuriHalInfraredTxSignalSentISRCallback callback,
|
||||
void* context);
|
||||
|
||||
/** Check if a module (like IR Blaster) is connected to PA7
|
||||
*
|
||||
* return true if a module is connected, false otherwise
|
||||
/** Detect which pin has an external IR module connected.
|
||||
*
|
||||
* External IR modules are detected by enabling a weak pull-up
|
||||
* on supported pins and testing whether the input is still low.
|
||||
*
|
||||
* This method works best on modules that employ a FET with a
|
||||
* strong pull-down or a BJT for driving IR LEDs.
|
||||
*
|
||||
* The module MUST pull the input voltage down to at least 0.9V
|
||||
* or lower in order for it to be detected.
|
||||
*
|
||||
* If no module has been detected, FuriHalInfraredTxPinInternal is returned.
|
||||
*
|
||||
* @return numeric identifier of the first pin with a module detected.
|
||||
*/
|
||||
bool furi_hal_infrared_is_external_connected();
|
||||
FuriHalInfraredTxPin furi_hal_infrared_detect_tx_output(void);
|
||||
|
||||
/** Set auto detect
|
||||
*
|
||||
* if enabled, external IR is used automatic if connected, otherwise internal IR is used
|
||||
*/
|
||||
void furi_hal_infrared_set_auto_detect(bool enable);
|
||||
|
||||
/** Check if auto detect is enabled
|
||||
*
|
||||
* @return true if enabled, false otherwise
|
||||
/** Set which pin will be used to transmit infrared signals.
|
||||
*
|
||||
* @param[in] tx_pin pin to be used for signal transmission.
|
||||
*/
|
||||
bool furi_hal_infrared_is_auto_detect_enabled();
|
||||
void furi_hal_infrared_set_tx_output(FuriHalInfraredTxPin tx_pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ extern "C" {
|
||||
/** Max number of simultaneously pressed keys (consumer control) */
|
||||
#define HID_CONSUMER_MAX_KEYS 2
|
||||
|
||||
/** OS-specific consumer keys, defined as "Reserved" in HID Usage Tables document */
|
||||
#define HID_CONSUMER_BRIGHTNESS_INCREMENT 0x006F
|
||||
#define HID_CONSUMER_BRIGHTNESS_DECREMENT 0x0070
|
||||
#define HID_CONSUMER_FN_GLOBE 0x029D
|
||||
|
||||
#define HID_KEYBOARD_NONE 0x00
|
||||
|
||||
/** HID keyboard modifier keys */
|
||||
@@ -265,6 +270,11 @@ bool furi_hal_hid_consumer_key_press(uint16_t button);
|
||||
*/
|
||||
bool furi_hal_hid_consumer_key_release(uint16_t button);
|
||||
|
||||
/** Clear all pressed consumer keys and send HID report
|
||||
*
|
||||
*/
|
||||
bool furi_hal_hid_consumer_key_release_all(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user