mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
Merge remote-tracking branch 'OFW/dev' into dev
This commit is contained in:
1
.vscode/example/settings.json.tmpl
vendored
1
.vscode/example/settings.json.tmpl
vendored
@@ -12,6 +12,7 @@
|
|||||||
"SConstruct": "python",
|
"SConstruct": "python",
|
||||||
"*.fam": "python"
|
"*.fam": "python"
|
||||||
},
|
},
|
||||||
|
"clangd.checkUpdates": false,
|
||||||
"clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
|
"clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
|
||||||
"clangd.arguments": [
|
"clangd.arguments": [
|
||||||
"--query-driver=**/arm-none-eabi-*",
|
"--query-driver=**/arm-none-eabi-*",
|
||||||
|
|||||||
@@ -37,6 +37,31 @@ bool hid_usb_kb_release(void* inst, uint16_t button) {
|
|||||||
return furi_hal_hid_kb_release(button);
|
return furi_hal_hid_kb_release(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hid_usb_mouse_press(void* inst, uint8_t button) {
|
||||||
|
UNUSED(inst);
|
||||||
|
return furi_hal_hid_mouse_press(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hid_usb_mouse_release(void* inst, uint8_t button) {
|
||||||
|
UNUSED(inst);
|
||||||
|
return furi_hal_hid_mouse_release(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hid_usb_mouse_scroll(void* inst, int8_t delta) {
|
||||||
|
UNUSED(inst);
|
||||||
|
return furi_hal_hid_mouse_scroll(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hid_usb_mouse_move(void* inst, int8_t dx, int8_t dy) {
|
||||||
|
UNUSED(inst);
|
||||||
|
return furi_hal_hid_mouse_move(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hid_usb_mouse_release_all(void* inst) {
|
||||||
|
UNUSED(inst);
|
||||||
|
return furi_hal_hid_mouse_release(0);
|
||||||
|
}
|
||||||
|
|
||||||
bool hid_usb_consumer_press(void* inst, uint16_t button) {
|
bool hid_usb_consumer_press(void* inst, uint16_t button) {
|
||||||
UNUSED(inst);
|
UNUSED(inst);
|
||||||
return furi_hal_hid_consumer_key_press(button);
|
return furi_hal_hid_consumer_key_press(button);
|
||||||
@@ -51,6 +76,7 @@ bool hid_usb_release_all(void* inst) {
|
|||||||
UNUSED(inst);
|
UNUSED(inst);
|
||||||
bool state = furi_hal_hid_kb_release_all();
|
bool state = furi_hal_hid_kb_release_all();
|
||||||
state &= furi_hal_hid_consumer_key_release_all();
|
state &= furi_hal_hid_consumer_key_release_all();
|
||||||
|
state &= hid_usb_mouse_release_all(inst);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +93,10 @@ static const BadUsbHidApi hid_api_usb = {
|
|||||||
|
|
||||||
.kb_press = hid_usb_kb_press,
|
.kb_press = hid_usb_kb_press,
|
||||||
.kb_release = hid_usb_kb_release,
|
.kb_release = hid_usb_kb_release,
|
||||||
|
.mouse_press = hid_usb_mouse_press,
|
||||||
|
.mouse_release = hid_usb_mouse_release,
|
||||||
|
.mouse_scroll = hid_usb_mouse_scroll,
|
||||||
|
.mouse_move = hid_usb_mouse_move,
|
||||||
.consumer_press = hid_usb_consumer_press,
|
.consumer_press = hid_usb_consumer_press,
|
||||||
.consumer_release = hid_usb_consumer_release,
|
.consumer_release = hid_usb_consumer_release,
|
||||||
.release_all = hid_usb_release_all,
|
.release_all = hid_usb_release_all,
|
||||||
@@ -157,6 +187,27 @@ bool hid_ble_kb_release(void* inst, uint16_t button) {
|
|||||||
return ble_profile_hid_kb_release(ble_hid->profile, button);
|
return ble_profile_hid_kb_release(ble_hid->profile, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hid_ble_mouse_press(void* inst, uint8_t button) {
|
||||||
|
BleHidInstance* ble_hid = inst;
|
||||||
|
furi_assert(ble_hid);
|
||||||
|
return ble_profile_hid_mouse_press(ble_hid->profile, button);
|
||||||
|
}
|
||||||
|
bool hid_ble_mouse_release(void* inst, uint8_t button) {
|
||||||
|
BleHidInstance* ble_hid = inst;
|
||||||
|
furi_assert(ble_hid);
|
||||||
|
return ble_profile_hid_mouse_release(ble_hid->profile, button);
|
||||||
|
}
|
||||||
|
bool hid_ble_mouse_scroll(void* inst, int8_t delta) {
|
||||||
|
BleHidInstance* ble_hid = inst;
|
||||||
|
furi_assert(ble_hid);
|
||||||
|
return ble_profile_hid_mouse_scroll(ble_hid->profile, delta);
|
||||||
|
}
|
||||||
|
bool hid_ble_mouse_move(void* inst, int8_t dx, int8_t dy) {
|
||||||
|
BleHidInstance* ble_hid = inst;
|
||||||
|
furi_assert(ble_hid);
|
||||||
|
return ble_profile_hid_mouse_move(ble_hid->profile, dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
bool hid_ble_consumer_press(void* inst, uint16_t button) {
|
bool hid_ble_consumer_press(void* inst, uint16_t button) {
|
||||||
BleHidInstance* ble_hid = inst;
|
BleHidInstance* ble_hid = inst;
|
||||||
furi_assert(ble_hid);
|
furi_assert(ble_hid);
|
||||||
@@ -174,6 +225,7 @@ bool hid_ble_release_all(void* inst) {
|
|||||||
furi_assert(ble_hid);
|
furi_assert(ble_hid);
|
||||||
bool state = ble_profile_hid_kb_release_all(ble_hid->profile);
|
bool state = ble_profile_hid_kb_release_all(ble_hid->profile);
|
||||||
state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile);
|
state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile);
|
||||||
|
state &= ble_profile_hid_mouse_release_all(ble_hid->profile);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +243,10 @@ static const BadUsbHidApi hid_api_ble = {
|
|||||||
|
|
||||||
.kb_press = hid_ble_kb_press,
|
.kb_press = hid_ble_kb_press,
|
||||||
.kb_release = hid_ble_kb_release,
|
.kb_release = hid_ble_kb_release,
|
||||||
|
.mouse_press = hid_ble_mouse_press,
|
||||||
|
.mouse_release = hid_ble_mouse_release,
|
||||||
|
.mouse_scroll = hid_ble_mouse_scroll,
|
||||||
|
.mouse_move = hid_ble_mouse_move,
|
||||||
.consumer_press = hid_ble_consumer_press,
|
.consumer_press = hid_ble_consumer_press,
|
||||||
.consumer_release = hid_ble_consumer_release,
|
.consumer_release = hid_ble_consumer_release,
|
||||||
.release_all = hid_ble_release_all,
|
.release_all = hid_ble_release_all,
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ typedef struct {
|
|||||||
|
|
||||||
bool (*kb_press)(void* inst, uint16_t button);
|
bool (*kb_press)(void* inst, uint16_t button);
|
||||||
bool (*kb_release)(void* inst, uint16_t button);
|
bool (*kb_release)(void* inst, uint16_t button);
|
||||||
|
bool (*mouse_press)(void* inst, uint8_t button);
|
||||||
|
bool (*mouse_release)(void* inst, uint8_t button);
|
||||||
|
bool (*mouse_scroll)(void* inst, int8_t delta);
|
||||||
|
bool (*mouse_move)(void* inst, int8_t dx, int8_t dy);
|
||||||
bool (*consumer_press)(void* inst, uint16_t button);
|
bool (*consumer_press)(void* inst, uint16_t button);
|
||||||
bool (*consumer_release)(void* inst, uint16_t button);
|
bool (*consumer_release)(void* inst, uint16_t button);
|
||||||
bool (*release_all)(void* inst);
|
bool (*release_all)(void* inst);
|
||||||
|
|||||||
@@ -193,8 +193,16 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
|
|||||||
return cmd_result;
|
return cmd_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mouse Keys
|
||||||
|
uint16_t key = ducky_get_mouse_keycode_by_name(line_tmp);
|
||||||
|
if(key != HID_MOUSE_INVALID) {
|
||||||
|
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
|
||||||
|
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Special keys + modifiers
|
// Special keys + modifiers
|
||||||
uint16_t key = ducky_get_keycode(bad_usb, line_tmp, false);
|
key = ducky_get_keycode(bad_usb, line_tmp, false);
|
||||||
if(key == HID_KEYBOARD_NONE) {
|
if(key == HID_KEYBOARD_NONE) {
|
||||||
return ducky_error(bad_usb, "No keycode defined for %s", line_tmp);
|
return ducky_error(bad_usb, "No keycode defined for %s", line_tmp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
#include <lib/toolbox/strint.h>
|
||||||
#include "ducky_script.h"
|
#include "ducky_script.h"
|
||||||
#include "ducky_script_i.h"
|
#include "ducky_script_i.h"
|
||||||
|
|
||||||
@@ -124,36 +125,60 @@ static int32_t ducky_fnc_altstring(BadUsbScript* bad_usb, const char* line, int3
|
|||||||
|
|
||||||
static int32_t ducky_fnc_hold(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
static int32_t ducky_fnc_hold(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||||
UNUSED(param);
|
UNUSED(param);
|
||||||
|
|
||||||
line = &line[ducky_get_command_len(line) + 1];
|
line = &line[ducky_get_command_len(line) + 1];
|
||||||
uint16_t key = ducky_get_keycode(bad_usb, line, true);
|
|
||||||
if(key == HID_KEYBOARD_NONE) {
|
|
||||||
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
|
||||||
}
|
|
||||||
bad_usb->key_hold_nb++;
|
|
||||||
if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
|
if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) {
|
||||||
return ducky_error(bad_usb, "Too many keys are hold");
|
return ducky_error(bad_usb, "Too many keys are held");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Mouse Keys here
|
||||||
|
uint16_t key = ducky_get_mouse_keycode_by_name(line);
|
||||||
|
if(key != HID_MOUSE_NONE) {
|
||||||
|
bad_usb->key_hold_nb++;
|
||||||
|
bad_usb->hid->mouse_press(bad_usb->hid_inst, key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Keyboard keys here
|
||||||
|
key = ducky_get_keycode(bad_usb, line, true);
|
||||||
|
if(key != HID_KEYBOARD_NONE) {
|
||||||
|
bad_usb->key_hold_nb++;
|
||||||
bad_usb->hid->kb_press(bad_usb->hid_inst, key);
|
bad_usb->hid->kb_press(bad_usb->hid_inst, key);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keyboard and mouse were none
|
||||||
|
return ducky_error(bad_usb, "Unknown keycode for %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
static int32_t ducky_fnc_release(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||||
UNUSED(param);
|
UNUSED(param);
|
||||||
|
|
||||||
line = &line[ducky_get_command_len(line) + 1];
|
line = &line[ducky_get_command_len(line) + 1];
|
||||||
uint16_t key = ducky_get_keycode(bad_usb, line, true);
|
|
||||||
if(key == HID_KEYBOARD_NONE) {
|
|
||||||
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
|
||||||
}
|
|
||||||
if(bad_usb->key_hold_nb == 0) {
|
if(bad_usb->key_hold_nb == 0) {
|
||||||
return ducky_error(bad_usb, "No keys are hold");
|
return ducky_error(bad_usb, "No keys are held");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Mouse Keys here
|
||||||
|
uint16_t key = ducky_get_mouse_keycode_by_name(line);
|
||||||
|
if(key != HID_MOUSE_NONE) {
|
||||||
|
bad_usb->key_hold_nb--;
|
||||||
|
bad_usb->hid->mouse_release(bad_usb->hid_inst, key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Handle Keyboard Keys here
|
||||||
|
key = ducky_get_keycode(bad_usb, line, true);
|
||||||
|
if(key != HID_KEYBOARD_NONE) {
|
||||||
bad_usb->key_hold_nb--;
|
bad_usb->key_hold_nb--;
|
||||||
bad_usb->hid->kb_release(bad_usb->hid_inst, key);
|
bad_usb->hid->kb_release(bad_usb->hid_inst, key);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// keyboard and mouse were none
|
||||||
|
return ducky_error(bad_usb, "No keycode defined for %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t ducky_fnc_media(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
static int32_t ducky_fnc_media(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||||
UNUSED(param);
|
UNUSED(param);
|
||||||
|
|
||||||
@@ -191,6 +216,43 @@ static int32_t ducky_fnc_waitforbutton(BadUsbScript* bad_usb, const char* line,
|
|||||||
return SCRIPT_STATE_WAIT_FOR_BTN;
|
return SCRIPT_STATE_WAIT_FOR_BTN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t ducky_fnc_mouse_scroll(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||||
|
UNUSED(param);
|
||||||
|
|
||||||
|
line = &line[strcspn(line, " ") + 1];
|
||||||
|
int32_t mouse_scroll_dist = 0;
|
||||||
|
|
||||||
|
if(strint_to_int32(line, NULL, &mouse_scroll_dist, 10) != StrintParseNoError) {
|
||||||
|
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bad_usb->hid->mouse_scroll(bad_usb->hid_inst, mouse_scroll_dist);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t ducky_fnc_mouse_move(BadUsbScript* bad_usb, const char* line, int32_t param) {
|
||||||
|
UNUSED(param);
|
||||||
|
|
||||||
|
line = &line[strcspn(line, " ") + 1];
|
||||||
|
int32_t mouse_move_x = 0;
|
||||||
|
int32_t mouse_move_y = 0;
|
||||||
|
|
||||||
|
if(strint_to_int32(line, NULL, &mouse_move_x, 10) != StrintParseNoError) {
|
||||||
|
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
line = &line[strcspn(line, " ") + 1];
|
||||||
|
|
||||||
|
if(strint_to_int32(line, NULL, &mouse_move_y, 10) != StrintParseNoError) {
|
||||||
|
return ducky_error(bad_usb, "Invalid Number %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bad_usb->hid->mouse_move(bad_usb->hid_inst, mouse_move_x, mouse_move_y);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const DuckyCmd ducky_commands[] = {
|
static const DuckyCmd ducky_commands[] = {
|
||||||
{"REM", NULL, -1},
|
{"REM", NULL, -1},
|
||||||
{"ID", NULL, -1},
|
{"ID", NULL, -1},
|
||||||
@@ -213,6 +275,10 @@ static const DuckyCmd ducky_commands[] = {
|
|||||||
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
|
{"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1},
|
||||||
{"MEDIA", ducky_fnc_media, -1},
|
{"MEDIA", ducky_fnc_media, -1},
|
||||||
{"GLOBE", ducky_fnc_globe, -1},
|
{"GLOBE", ducky_fnc_globe, -1},
|
||||||
|
{"MOUSEMOVE", ducky_fnc_mouse_move, -1},
|
||||||
|
{"MOUSE_MOVE", ducky_fnc_mouse_move, -1},
|
||||||
|
{"MOUSESCROLL", ducky_fnc_mouse_scroll, -1},
|
||||||
|
{"MOUSE_SCROLL", ducky_fnc_mouse_scroll, -1},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TAG "BadUsb"
|
#define TAG "BadUsb"
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ extern "C" {
|
|||||||
|
|
||||||
#define FILE_BUFFER_LEN 16
|
#define FILE_BUFFER_LEN 16
|
||||||
|
|
||||||
|
#define HID_MOUSE_INVALID 0
|
||||||
|
#define HID_MOUSE_NONE 0
|
||||||
|
|
||||||
struct BadUsbScript {
|
struct BadUsbScript {
|
||||||
FuriHalUsbHidConfig hid_cfg;
|
FuriHalUsbHidConfig hid_cfg;
|
||||||
const BadUsbHidApi* hid;
|
const BadUsbHidApi* hid;
|
||||||
@@ -55,6 +58,8 @@ uint16_t ducky_get_keycode_by_name(const char* param);
|
|||||||
|
|
||||||
uint16_t ducky_get_media_keycode_by_name(const char* param);
|
uint16_t ducky_get_media_keycode_by_name(const char* param);
|
||||||
|
|
||||||
|
uint8_t ducky_get_mouse_keycode_by_name(const char* param);
|
||||||
|
|
||||||
bool ducky_get_number(const char* param, uint32_t* val);
|
bool ducky_get_number(const char* param, uint32_t* val);
|
||||||
|
|
||||||
void ducky_numlock_on(BadUsbScript* bad_usb);
|
void ducky_numlock_on(BadUsbScript* bad_usb);
|
||||||
|
|||||||
@@ -108,6 +108,17 @@ static const DuckyKey ducky_media_keys[] = {
|
|||||||
{"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT},
|
{"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const DuckyKey ducky_mouse_keys[] = {
|
||||||
|
{"LEFTCLICK", HID_MOUSE_BTN_LEFT},
|
||||||
|
{"LEFT_CLICK", HID_MOUSE_BTN_LEFT},
|
||||||
|
{"RIGHTCLICK", HID_MOUSE_BTN_RIGHT},
|
||||||
|
{"RIGHT_CLICK", HID_MOUSE_BTN_RIGHT},
|
||||||
|
{"MIDDLECLICK", HID_MOUSE_BTN_WHEEL},
|
||||||
|
{"MIDDLE_CLICK", HID_MOUSE_BTN_WHEEL},
|
||||||
|
{"WHEELCLICK", HID_MOUSE_BTN_WHEEL},
|
||||||
|
{"WHEEL_CLICK", HID_MOUSE_BTN_WHEEL},
|
||||||
|
};
|
||||||
|
|
||||||
uint16_t ducky_get_keycode_by_name(const char* param) {
|
uint16_t ducky_get_keycode_by_name(const char* param) {
|
||||||
for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) {
|
for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) {
|
||||||
size_t key_cmd_len = strlen(ducky_keys[i].name);
|
size_t key_cmd_len = strlen(ducky_keys[i].name);
|
||||||
@@ -131,3 +142,15 @@ uint16_t ducky_get_media_keycode_by_name(const char* param) {
|
|||||||
|
|
||||||
return HID_CONSUMER_UNASSIGNED;
|
return HID_CONSUMER_UNASSIGNED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t ducky_get_mouse_keycode_by_name(const char* param) {
|
||||||
|
for(size_t i = 0; i < COUNT_OF(ducky_mouse_keys); i++) {
|
||||||
|
size_t key_cmd_len = strlen(ducky_mouse_keys[i].name);
|
||||||
|
if((strncmp(param, ducky_mouse_keys[i].name, key_cmd_len) == 0) &&
|
||||||
|
(ducky_is_line_end(param[key_cmd_len]))) {
|
||||||
|
return ducky_mouse_keys[i].keycode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HID_MOUSE_INVALID;
|
||||||
|
}
|
||||||
|
|||||||
46
applications/main/bad_usb/resources/badusb/test_mouse.txt
Normal file
46
applications/main/bad_usb/resources/badusb/test_mouse.txt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
ID 1234:abcd Generic:USB Keyboard
|
||||||
|
REM Declare ourselves as a generic usb keyboard
|
||||||
|
REM You can override this to use something else
|
||||||
|
REM Check the `lsusb` command to know your own devices IDs
|
||||||
|
|
||||||
|
DEFAULT_DELAY 200
|
||||||
|
DEFAULT_STRING_DELAY 100
|
||||||
|
|
||||||
|
DELAY 1000
|
||||||
|
|
||||||
|
REM Test all mouse functions
|
||||||
|
LEFTCLICK
|
||||||
|
RIGHTCLICK
|
||||||
|
MIDDLECLICK
|
||||||
|
|
||||||
|
DELAY 1000
|
||||||
|
|
||||||
|
MOUSEMOVE -10 0
|
||||||
|
REPEAT 20
|
||||||
|
MOUSEMOVE 0 10
|
||||||
|
REPEAT 20
|
||||||
|
MOUSEMOVE 10 0
|
||||||
|
REPEAT 20
|
||||||
|
MOUSEMOVE 0 -10
|
||||||
|
REPEAT 20
|
||||||
|
|
||||||
|
DELAY 1000
|
||||||
|
|
||||||
|
MOUSESCROLL -50
|
||||||
|
MOUSESCROLL 50
|
||||||
|
|
||||||
|
DELAY 1000
|
||||||
|
|
||||||
|
REM Verify Mouse hold working
|
||||||
|
HOLD LEFTCLICK
|
||||||
|
DELAY 2000
|
||||||
|
RELEASE LEFTCLICK
|
||||||
|
|
||||||
|
DELAY 1000
|
||||||
|
|
||||||
|
REM Verify KB hold working
|
||||||
|
HOLD M
|
||||||
|
DELAY 2000
|
||||||
|
RELEASE M
|
||||||
|
|
||||||
|
ENTER
|
||||||
@@ -2,26 +2,61 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <m-dict.h>
|
#include <m-dict.h>
|
||||||
|
#include <m-array.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
|
|
||||||
#include "infrared_signal.h"
|
#include "infrared_signal.h"
|
||||||
|
|
||||||
|
ARRAY_DEF(SignalPositionArray, size_t, M_DEFAULT_OPLIST);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t index;
|
size_t index;
|
||||||
uint32_t count;
|
SignalPositionArray_t signals;
|
||||||
} InfraredBruteForceRecord;
|
} InfraredBruteForceRecord;
|
||||||
|
|
||||||
|
static inline void ir_bf_record_init(InfraredBruteForceRecord* record) {
|
||||||
|
record->index = 0;
|
||||||
|
SignalPositionArray_init(record->signals);
|
||||||
|
}
|
||||||
|
#define IR_BF_RECORD_INIT(r) (ir_bf_record_init(&(r)))
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ir_bf_record_init_set(InfraredBruteForceRecord* dest, const InfraredBruteForceRecord* src) {
|
||||||
|
dest->index = src->index;
|
||||||
|
SignalPositionArray_init_set(dest->signals, src->signals);
|
||||||
|
}
|
||||||
|
#define IR_BF_RECORD_INIT_SET(d, s) (ir_bf_record_init_set(&(d), &(s)))
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ir_bf_record_set(InfraredBruteForceRecord* dest, const InfraredBruteForceRecord* src) {
|
||||||
|
dest->index = src->index;
|
||||||
|
SignalPositionArray_set(dest->signals, src->signals);
|
||||||
|
}
|
||||||
|
#define IR_BF_RECORD_SET(d, s) (ir_bf_record_set(&(d), &(s)))
|
||||||
|
|
||||||
|
static inline void ir_bf_record_clear(InfraredBruteForceRecord* record) {
|
||||||
|
SignalPositionArray_clear(record->signals);
|
||||||
|
}
|
||||||
|
#define IR_BF_RECORD_CLEAR(r) (ir_bf_record_clear(&(r)))
|
||||||
|
|
||||||
|
#define IR_BF_RECORD_OPLIST \
|
||||||
|
(INIT(IR_BF_RECORD_INIT), \
|
||||||
|
INIT_SET(IR_BF_RECORD_INIT_SET), \
|
||||||
|
SET(IR_BF_RECORD_SET), \
|
||||||
|
CLEAR(IR_BF_RECORD_CLEAR))
|
||||||
|
|
||||||
DICT_DEF2(
|
DICT_DEF2(
|
||||||
InfraredBruteForceRecordDict,
|
InfraredBruteForceRecordDict,
|
||||||
FuriString*,
|
FuriString*,
|
||||||
FURI_STRING_OPLIST,
|
FURI_STRING_OPLIST,
|
||||||
InfraredBruteForceRecord,
|
InfraredBruteForceRecord,
|
||||||
M_POD_OPLIST);
|
IR_BF_RECORD_OPLIST);
|
||||||
|
|
||||||
struct InfraredBruteForce {
|
struct InfraredBruteForce {
|
||||||
FlipperFormat* ff;
|
FlipperFormat* ff;
|
||||||
const char* db_filename;
|
const char* db_filename;
|
||||||
FuriString* current_record_name;
|
FuriString* current_record_name;
|
||||||
|
InfraredBruteForceRecord current_record;
|
||||||
InfraredSignal* current_signal;
|
InfraredSignal* current_signal;
|
||||||
InfraredBruteForceRecordDict_t records;
|
InfraredBruteForceRecordDict_t records;
|
||||||
bool is_started;
|
bool is_started;
|
||||||
@@ -39,6 +74,7 @@ InfraredBruteForce* infrared_brute_force_alloc(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void infrared_brute_force_free(InfraredBruteForce* brute_force) {
|
void infrared_brute_force_free(InfraredBruteForce* brute_force) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(!brute_force->is_started);
|
furi_assert(!brute_force->is_started);
|
||||||
InfraredBruteForceRecordDict_clear(brute_force->records);
|
InfraredBruteForceRecordDict_clear(brute_force->records);
|
||||||
furi_string_free(brute_force->current_record_name);
|
furi_string_free(brute_force->current_record_name);
|
||||||
@@ -46,11 +82,13 @@ void infrared_brute_force_free(InfraredBruteForce* brute_force) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename) {
|
void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(!brute_force->is_started);
|
furi_assert(!brute_force->is_started);
|
||||||
brute_force->db_filename = db_filename;
|
brute_force->db_filename = db_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(!brute_force->is_started);
|
furi_assert(!brute_force->is_started);
|
||||||
furi_assert(brute_force->db_filename);
|
furi_assert(brute_force->db_filename);
|
||||||
InfraredErrorCode error = InfraredErrorCodeNone;
|
InfraredErrorCode error = InfraredErrorCodeNone;
|
||||||
@@ -66,19 +104,19 @@ InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* br
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool signals_valid = false;
|
size_t signal_start = flipper_format_tell(ff);
|
||||||
|
bool signal_valid = false;
|
||||||
while(infrared_signal_read_name(ff, signal_name) == InfraredErrorCodeNone) {
|
while(infrared_signal_read_name(ff, signal_name) == InfraredErrorCodeNone) {
|
||||||
error = infrared_signal_read_body(signal, ff);
|
error = infrared_signal_read_body(signal, ff);
|
||||||
signals_valid = (!INFRARED_ERROR_PRESENT(error)) && infrared_signal_is_valid(signal);
|
signal_valid = (!INFRARED_ERROR_PRESENT(error)) && infrared_signal_is_valid(signal);
|
||||||
if(!signals_valid) break;
|
if(!signal_valid) break;
|
||||||
|
|
||||||
InfraredBruteForceRecord* record =
|
InfraredBruteForceRecord* record =
|
||||||
InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
|
InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
|
||||||
if(record) { //-V547
|
furi_assert(record);
|
||||||
++(record->count);
|
SignalPositionArray_push_back(record->signals, signal_start);
|
||||||
}
|
}
|
||||||
}
|
if(!signal_valid) break;
|
||||||
if(!signals_valid) break;
|
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
infrared_signal_free(signal);
|
infrared_signal_free(signal);
|
||||||
@@ -93,6 +131,7 @@ bool infrared_brute_force_start(
|
|||||||
InfraredBruteForce* brute_force,
|
InfraredBruteForce* brute_force,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
uint32_t* record_count) {
|
uint32_t* record_count) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(!brute_force->is_started);
|
furi_assert(!brute_force->is_started);
|
||||||
bool success = false;
|
bool success = false;
|
||||||
*record_count = 0;
|
*record_count = 0;
|
||||||
@@ -103,9 +142,10 @@ bool infrared_brute_force_start(
|
|||||||
InfraredBruteForceRecordDict_next(it)) {
|
InfraredBruteForceRecordDict_next(it)) {
|
||||||
const InfraredBruteForceRecordDict_itref_t* record = InfraredBruteForceRecordDict_cref(it);
|
const InfraredBruteForceRecordDict_itref_t* record = InfraredBruteForceRecordDict_cref(it);
|
||||||
if(record->value.index == index) {
|
if(record->value.index == index) {
|
||||||
*record_count = record->value.count;
|
*record_count = SignalPositionArray_size(record->value.signals);
|
||||||
if(*record_count) {
|
if(*record_count) {
|
||||||
furi_string_set(brute_force->current_record_name, record->key);
|
furi_string_set(brute_force->current_record_name, record->key);
|
||||||
|
brute_force->current_record = record->value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -124,10 +164,12 @@ bool infrared_brute_force_start(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force) {
|
bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force) {
|
||||||
|
furi_check(brute_force);
|
||||||
return brute_force->is_started;
|
return brute_force->is_started;
|
||||||
}
|
}
|
||||||
|
|
||||||
void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
|
void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(brute_force->is_started);
|
furi_assert(brute_force->is_started);
|
||||||
furi_string_reset(brute_force->current_record_name);
|
furi_string_reset(brute_force->current_record_name);
|
||||||
infrared_signal_free(brute_force->current_signal);
|
infrared_signal_free(brute_force->current_signal);
|
||||||
@@ -138,25 +180,32 @@ void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) {
|
bool infrared_brute_force_send(InfraredBruteForce* brute_force, uint32_t signal_index) {
|
||||||
|
furi_check(brute_force);
|
||||||
furi_assert(brute_force->is_started);
|
furi_assert(brute_force->is_started);
|
||||||
|
|
||||||
const bool success = infrared_signal_search_by_name_and_read(
|
if(signal_index >= SignalPositionArray_size(brute_force->current_record.signals)) return false;
|
||||||
brute_force->current_signal,
|
|
||||||
brute_force->ff,
|
size_t signal_start =
|
||||||
furi_string_get_cstr(brute_force->current_record_name)) ==
|
*SignalPositionArray_cget(brute_force->current_record.signals, signal_index);
|
||||||
InfraredErrorCodeNone;
|
if(!flipper_format_seek(brute_force->ff, signal_start, FlipperFormatOffsetFromStart))
|
||||||
if(success) {
|
return false;
|
||||||
|
|
||||||
|
if(INFRARED_ERROR_PRESENT(
|
||||||
|
infrared_signal_read_body(brute_force->current_signal, brute_force->ff)))
|
||||||
|
return false;
|
||||||
|
|
||||||
infrared_signal_transmit(brute_force->current_signal);
|
infrared_signal_transmit(brute_force->current_signal);
|
||||||
}
|
return true;
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void infrared_brute_force_add_record(
|
void infrared_brute_force_add_record(
|
||||||
InfraredBruteForce* brute_force,
|
InfraredBruteForce* brute_force,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
const char* name) {
|
const char* name) {
|
||||||
InfraredBruteForceRecord value = {.index = index, .count = 0};
|
InfraredBruteForceRecord value;
|
||||||
|
ir_bf_record_init(&value);
|
||||||
|
value.index = index;
|
||||||
FuriString* key;
|
FuriString* key;
|
||||||
key = furi_string_alloc_set(name);
|
key = furi_string_alloc_set(name);
|
||||||
InfraredBruteForceRecordDict_set_at(brute_force->records, key, value);
|
InfraredBruteForceRecordDict_set_at(brute_force->records, key, value);
|
||||||
|
|||||||
@@ -78,18 +78,16 @@ bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force);
|
|||||||
void infrared_brute_force_stop(InfraredBruteForce* brute_force);
|
void infrared_brute_force_stop(InfraredBruteForce* brute_force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send the next signal from the chosen category.
|
* @brief Send an arbitrary signal from the chosen category.
|
||||||
*
|
*
|
||||||
* This function is called repeatedly until no more signals are left
|
* @param[in] brute_force pointer to the instance
|
||||||
* in the chosen signal category.
|
* @param signal_index the index of the signal within the category, must be
|
||||||
|
* between 0 and `record_count` as told by
|
||||||
|
* `infrared_brute_force_start`
|
||||||
*
|
*
|
||||||
* @warning Transmission must be started first by calling infrared_brute_force_start()
|
* @returns true on success, false otherwise
|
||||||
* before calling this function.
|
|
||||||
*
|
|
||||||
* @param[in,out] brute_force pointer to the instance to be used.
|
|
||||||
* @returns true if the next signal existed and could be transmitted, false otherwise.
|
|
||||||
*/
|
*/
|
||||||
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force);
|
bool infrared_brute_force_send(InfraredBruteForce* brute_force, uint32_t signal_index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a signal category to an InfraredBruteForce instance's dictionary.
|
* @brief Add a signal category to an InfraredBruteForce instance's dictionary.
|
||||||
|
|||||||
@@ -475,25 +475,24 @@ static void
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t record_count;
|
uint32_t signal_count, current_signal = 0;
|
||||||
bool running = infrared_brute_force_start(
|
bool running = infrared_brute_force_start(
|
||||||
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, &record_count);
|
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, &signal_count);
|
||||||
|
|
||||||
if(record_count <= 0) {
|
if(signal_count <= 0) {
|
||||||
printf("Invalid signal name.\r\n");
|
printf("Invalid signal name.\r\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Sending %lu signal(s)...\r\n", record_count);
|
printf("Sending %lu signal(s)...\r\n", signal_count);
|
||||||
printf("Press Ctrl-C to stop.\r\n");
|
printf("Press Ctrl-C to stop.\r\n");
|
||||||
|
|
||||||
int records_sent = 0;
|
|
||||||
while(running) {
|
while(running) {
|
||||||
running = infrared_brute_force_send_next(brute_force);
|
running = infrared_brute_force_send(brute_force, current_signal);
|
||||||
|
|
||||||
if(cli_cmd_interrupt_received(cli)) break;
|
if(cli_cmd_interrupt_received(cli)) break;
|
||||||
|
|
||||||
printf("\r%d%% complete.", (int)((float)records_sent++ / (float)record_count * 100));
|
printf("\r%d%% complete.", (int)((float)current_signal++ / (float)signal_count * 100));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
enum InfraredCustomEventType {
|
typedef enum {
|
||||||
// Reserve first 100 events for button types and indexes, starting from 0
|
// Reserve first 100 events for button types and indexes, starting from 0
|
||||||
InfraredCustomEventTypeReserved = 100,
|
InfraredCustomEventTypeReserved = 100,
|
||||||
InfraredCustomEventTypeMenuSelected,
|
InfraredCustomEventTypeMenuSelected,
|
||||||
@@ -13,7 +13,7 @@ enum InfraredCustomEventType {
|
|||||||
InfraredCustomEventTypeTextEditDone,
|
InfraredCustomEventTypeTextEditDone,
|
||||||
InfraredCustomEventTypePopupClosed,
|
InfraredCustomEventTypePopupClosed,
|
||||||
InfraredCustomEventTypeButtonSelected,
|
InfraredCustomEventTypeButtonSelected,
|
||||||
InfraredCustomEventTypeBackPressed,
|
InfraredCustomEventTypePopupInput,
|
||||||
InfraredCustomEventTypeTaskFinished,
|
InfraredCustomEventTypeTaskFinished,
|
||||||
|
|
||||||
InfraredCustomEventTypeRpcLoadFile,
|
InfraredCustomEventTypeRpcLoadFile,
|
||||||
@@ -27,7 +27,7 @@ enum InfraredCustomEventType {
|
|||||||
|
|
||||||
InfraredCustomEventTypeGpioTxPinChanged,
|
InfraredCustomEventTypeGpioTxPinChanged,
|
||||||
InfraredCustomEventTypeGpioOtgChanged,
|
InfraredCustomEventTypeGpioOtgChanged,
|
||||||
};
|
} InfraredCustomEventType;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
@@ -2,15 +2,28 @@
|
|||||||
|
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
typedef union {
|
||||||
|
uint32_t packed_value;
|
||||||
|
struct {
|
||||||
|
bool is_paused;
|
||||||
|
uint8_t padding;
|
||||||
|
uint16_t signal_index;
|
||||||
|
};
|
||||||
|
} InfraredSceneState;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
void infrared_scene_universal_common_item_callback(void* context, uint32_t index) {
|
void infrared_scene_universal_common_item_callback(void* context, uint32_t index) {
|
||||||
InfraredApp* infrared = context;
|
InfraredApp* infrared = context;
|
||||||
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeButtonSelected, index);
|
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeButtonSelected, index);
|
||||||
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
|
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void infrared_scene_universal_common_progress_back_callback(void* context) {
|
static void infrared_scene_universal_common_progress_input_callback(
|
||||||
|
void* context,
|
||||||
|
InfraredProgressViewInput input) {
|
||||||
InfraredApp* infrared = context;
|
InfraredApp* infrared = context;
|
||||||
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypeBackPressed, -1);
|
uint32_t event = infrared_custom_event_pack(InfraredCustomEventTypePopupInput, input);
|
||||||
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
|
view_dispatcher_send_custom_event(infrared->view_dispatcher, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,8 +32,8 @@ static void
|
|||||||
ViewStack* view_stack = infrared->view_stack;
|
ViewStack* view_stack = infrared->view_stack;
|
||||||
InfraredProgressView* progress = infrared->progress;
|
InfraredProgressView* progress = infrared->progress;
|
||||||
infrared_progress_view_set_progress_total(progress, record_count);
|
infrared_progress_view_set_progress_total(progress, record_count);
|
||||||
infrared_progress_view_set_back_callback(
|
infrared_progress_view_set_input_callback(
|
||||||
progress, infrared_scene_universal_common_progress_back_callback, infrared);
|
progress, infrared_scene_universal_common_progress_input_callback, infrared);
|
||||||
view_stack_add_view(view_stack, infrared_progress_view_get_view(progress));
|
view_stack_add_view(view_stack, infrared_progress_view_get_view(progress));
|
||||||
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||||
}
|
}
|
||||||
@@ -51,30 +64,112 @@ void infrared_scene_universal_common_on_enter(void* context) {
|
|||||||
infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback);
|
infrared_blocking_task_start(infrared, infrared_scene_universal_common_task_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void infrared_scene_universal_common_handle_popup_input(
|
||||||
|
InfraredApp* infrared,
|
||||||
|
InfraredProgressViewInput input) {
|
||||||
|
InfraredBruteForce* brute_force = infrared->brute_force;
|
||||||
|
SceneManager* scene_manager = infrared->scene_manager;
|
||||||
|
uint32_t scene_id = scene_manager_get_current_scene(infrared->scene_manager);
|
||||||
|
switch(input) {
|
||||||
|
case InfraredProgressViewInputStop: {
|
||||||
|
infrared_brute_force_stop(brute_force);
|
||||||
|
infrared_scene_universal_common_hide_popup(infrared);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InfraredProgressViewInputPause: {
|
||||||
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||||
|
infrared_progress_view_set_paused(infrared->progress, true);
|
||||||
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
scene_state.is_paused = true;
|
||||||
|
if(scene_state.signal_index)
|
||||||
|
scene_state.signal_index--; // when running, the state stores the next index
|
||||||
|
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InfraredProgressViewInputResume: {
|
||||||
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||||
|
infrared_progress_view_set_paused(infrared->progress, false);
|
||||||
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
scene_state.is_paused = false;
|
||||||
|
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InfraredProgressViewInputNextSignal: {
|
||||||
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
scene_state.signal_index++;
|
||||||
|
if(infrared_progress_view_set_progress(infrared->progress, scene_state.signal_index + 1))
|
||||||
|
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InfraredProgressViewInputPreviousSignal: {
|
||||||
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
if(scene_state.signal_index) {
|
||||||
|
scene_state.signal_index--;
|
||||||
|
if(infrared_progress_view_set_progress(
|
||||||
|
infrared->progress, scene_state.signal_index + 1))
|
||||||
|
scene_manager_set_scene_state(scene_manager, scene_id, scene_state.packed_value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InfraredProgressViewInputSendSingle: {
|
||||||
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStartSend);
|
||||||
|
infrared_brute_force_send(infrared->brute_force, scene_state.signal_index);
|
||||||
|
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
furi_crash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) {
|
bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent event) {
|
||||||
InfraredApp* infrared = context;
|
InfraredApp* infrared = context;
|
||||||
SceneManager* scene_manager = infrared->scene_manager;
|
SceneManager* scene_manager = infrared->scene_manager;
|
||||||
InfraredBruteForce* brute_force = infrared->brute_force;
|
InfraredBruteForce* brute_force = infrared->brute_force;
|
||||||
|
uint32_t scene_id = scene_manager_get_current_scene(infrared->scene_manager);
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(infrared_brute_force_is_started(brute_force)) {
|
if(infrared_brute_force_is_started(brute_force)) {
|
||||||
if(event.type == SceneManagerEventTypeTick) {
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
bool success = infrared_brute_force_send_next(brute_force);
|
InfraredSceneState scene_state = {
|
||||||
|
.packed_value = scene_manager_get_scene_state(scene_manager, scene_id)};
|
||||||
|
|
||||||
|
if(!scene_state.is_paused) {
|
||||||
|
bool success = infrared_brute_force_send(brute_force, scene_state.signal_index);
|
||||||
if(success) {
|
if(success) {
|
||||||
success = infrared_progress_view_increase_progress(infrared->progress);
|
success = infrared_progress_view_set_progress(
|
||||||
|
infrared->progress, scene_state.signal_index + 1);
|
||||||
|
scene_state.signal_index++;
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
scene_manager, scene_id, scene_state.packed_value);
|
||||||
}
|
}
|
||||||
if(!success) {
|
if(!success) {
|
||||||
infrared_brute_force_stop(brute_force);
|
infrared_brute_force_stop(brute_force);
|
||||||
infrared_scene_universal_common_hide_popup(infrared);
|
infrared_scene_universal_common_hide_popup(infrared);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
|
||||||
if(infrared_custom_event_get_type(event.event) == InfraredCustomEventTypeBackPressed) {
|
|
||||||
infrared_brute_force_stop(brute_force);
|
|
||||||
infrared_scene_universal_common_hide_popup(infrared);
|
|
||||||
}
|
}
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
uint16_t event_type;
|
||||||
|
int16_t event_value;
|
||||||
|
infrared_custom_event_unpack(event.event, &event_type, &event_value);
|
||||||
|
if(event_type == InfraredCustomEventTypePopupInput) {
|
||||||
|
infrared_scene_universal_common_handle_popup_input(infrared, event_value);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if(event.type == SceneManagerEventTypeBack) {
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
scene_manager_previous_scene(scene_manager);
|
scene_manager_previous_scene(scene_manager);
|
||||||
@@ -87,6 +182,7 @@ bool infrared_scene_universal_common_on_event(void* context, SceneManagerEvent e
|
|||||||
if(event_type == InfraredCustomEventTypeButtonSelected) {
|
if(event_type == InfraredCustomEventTypeButtonSelected) {
|
||||||
uint32_t record_count;
|
uint32_t record_count;
|
||||||
if(infrared_brute_force_start(brute_force, event_value, &record_count)) {
|
if(infrared_brute_force_start(brute_force, event_value, &record_count)) {
|
||||||
|
scene_manager_set_scene_state(infrared->scene_manager, scene_id, 0);
|
||||||
dolphin_deed(DolphinDeedIrSend);
|
dolphin_deed(DolphinDeedIrSend);
|
||||||
infrared_scene_universal_common_show_popup(infrared, record_count);
|
infrared_scene_universal_common_show_popup(infrared, record_count);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ void infrared_scene_universal_ac_on_enter(void* context) {
|
|||||||
button_panel_add_icon(button_panel, 0, 60, &I_cool_30x51);
|
button_panel_add_icon(button_panel, 0, 60, &I_cool_30x51);
|
||||||
button_panel_add_icon(button_panel, 34, 60, &I_heat_30x51);
|
button_panel_add_icon(button_panel, 34, 60, &I_heat_30x51);
|
||||||
|
|
||||||
button_panel_add_label(button_panel, 4, 10, FontPrimary, "AC remote");
|
button_panel_add_label(button_panel, 24, 10, FontPrimary, "AC");
|
||||||
|
|
||||||
infrared_scene_universal_common_on_enter(context);
|
infrared_scene_universal_common_on_enter(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ void infrared_scene_universal_audio_on_enter(void* context) {
|
|||||||
context);
|
context);
|
||||||
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
|
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
|
||||||
|
|
||||||
button_panel_add_label(button_panel, 1, 10, FontPrimary, "Mus. remote");
|
button_panel_add_label(button_panel, 1, 10, FontPrimary, "Audio player");
|
||||||
button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30);
|
button_panel_add_icon(button_panel, 34, 56, &I_vol_ac_text_30x30);
|
||||||
|
|
||||||
infrared_scene_universal_common_on_enter(context);
|
infrared_scene_universal_common_on_enter(context);
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ void infrared_scene_universal_projector_on_enter(void* context) {
|
|||||||
infrared_brute_force_add_record(brute_force, i++, "Pause");
|
infrared_brute_force_add_record(brute_force, i++, "Pause");
|
||||||
button_panel_add_icon(button_panel, 4, 109, &I_pause_text_23x5);
|
button_panel_add_icon(button_panel, 4, 109, &I_pause_text_23x5);
|
||||||
|
|
||||||
button_panel_add_label(button_panel, 3, 11, FontPrimary, "Proj. remote");
|
button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector");
|
||||||
button_panel_add_icon(button_panel, 34, 68, &I_vol_ac_text_30x30);
|
button_panel_add_icon(button_panel, 17, 72, &I_vol_ac_text_30x30);
|
||||||
|
|
||||||
infrared_scene_universal_common_on_enter(context);
|
infrared_scene_universal_common_on_enter(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
|
|||||||
context);
|
context);
|
||||||
infrared_brute_force_add_record(brute_force, i++, "Ch_prev");
|
infrared_brute_force_add_record(brute_force, i++, "Ch_prev");
|
||||||
|
|
||||||
button_panel_add_label(button_panel, 5, 10, FontPrimary, "TV remote");
|
button_panel_add_label(button_panel, 25, 10, FontPrimary, "TV");
|
||||||
|
|
||||||
infrared_scene_universal_common_on_enter(context);
|
infrared_scene_universal_common_on_enter(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,54 +14,80 @@
|
|||||||
|
|
||||||
struct InfraredProgressView {
|
struct InfraredProgressView {
|
||||||
View* view;
|
View* view;
|
||||||
InfraredProgressViewBackCallback back_callback;
|
InfraredProgressViewInputCallback input_callback;
|
||||||
void* context;
|
void* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t progress;
|
size_t progress;
|
||||||
size_t progress_total;
|
size_t progress_total;
|
||||||
|
bool is_paused;
|
||||||
} InfraredProgressViewModel;
|
} InfraredProgressViewModel;
|
||||||
|
|
||||||
bool infrared_progress_view_increase_progress(InfraredProgressView* progress) {
|
|
||||||
furi_assert(progress);
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
InfraredProgressViewModel* model = view_get_model(progress->view);
|
|
||||||
if(model->progress < model->progress_total) {
|
|
||||||
++model->progress;
|
|
||||||
result = model->progress < model->progress_total;
|
|
||||||
}
|
|
||||||
view_commit_model(progress->view, true);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void infrared_progress_view_draw_callback(Canvas* canvas, void* _model) {
|
static void infrared_progress_view_draw_callback(Canvas* canvas, void* _model) {
|
||||||
InfraredProgressViewModel* model = (InfraredProgressViewModel*)_model;
|
InfraredProgressViewModel* model = (InfraredProgressViewModel*)_model;
|
||||||
|
|
||||||
uint8_t x = 0;
|
uint8_t x = 0;
|
||||||
uint8_t y = 36;
|
uint8_t y = 25;
|
||||||
uint8_t width = 63;
|
uint8_t width = 63;
|
||||||
uint8_t height = 59;
|
uint8_t height = 81;
|
||||||
|
|
||||||
elements_bold_rounded_frame(canvas, x, y, width, height);
|
elements_bold_rounded_frame(canvas, x, y, width, height);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
elements_multiline_text_aligned(
|
elements_multiline_text_aligned(
|
||||||
canvas, x + 34, y + 9, AlignCenter, AlignCenter, "Sending ...");
|
canvas,
|
||||||
|
x + 32,
|
||||||
|
y + 9,
|
||||||
|
AlignCenter,
|
||||||
|
AlignCenter,
|
||||||
|
model->is_paused ? "Paused" : "Sending...");
|
||||||
|
|
||||||
float progress_value = (float)model->progress / model->progress_total;
|
float progress_value = (float)model->progress / model->progress_total;
|
||||||
elements_progress_bar(canvas, x + 4, y + 19, width - 7, progress_value);
|
elements_progress_bar(canvas, x + 4, y + 19, width - 7, progress_value);
|
||||||
|
|
||||||
char number_string[10] = {0};
|
char progress_string[16] = {0};
|
||||||
|
if(model->is_paused) {
|
||||||
snprintf(
|
snprintf(
|
||||||
number_string, sizeof(number_string), "%d/%d", model->progress, model->progress_total);
|
progress_string,
|
||||||
|
sizeof(progress_string),
|
||||||
|
"%zu/%zu",
|
||||||
|
model->progress,
|
||||||
|
model->progress_total);
|
||||||
|
} else {
|
||||||
|
uint8_t percent_value = 100 * model->progress / model->progress_total;
|
||||||
|
snprintf(progress_string, sizeof(progress_string), "%d%%", percent_value);
|
||||||
|
}
|
||||||
elements_multiline_text_aligned(
|
elements_multiline_text_aligned(
|
||||||
canvas, x + 33, y + 37, AlignCenter, AlignCenter, number_string);
|
canvas, x + 33, y + 37, AlignCenter, AlignCenter, progress_string);
|
||||||
|
|
||||||
canvas_draw_icon(canvas, x + 14, y + height - 14, &I_Pin_back_arrow_10x8);
|
uint8_t buttons_x = x + (model->is_paused ? 10 : 14);
|
||||||
canvas_draw_str(canvas, x + 30, y + height - 6, "= stop");
|
uint8_t buttons_y = y + (model->is_paused ? 46 : 50);
|
||||||
|
|
||||||
|
canvas_draw_icon(canvas, buttons_x + 0, buttons_y + 0, &I_Pin_back_arrow_10x8);
|
||||||
|
canvas_draw_str(canvas, buttons_x + 14, buttons_y + 8, model->is_paused ? "resume" : "stop");
|
||||||
|
|
||||||
|
canvas_draw_icon(canvas, buttons_x + 1, buttons_y + 10, &I_Ok_btn_9x9);
|
||||||
|
canvas_draw_str(canvas, buttons_x + 14, buttons_y + 17, model->is_paused ? "send 1" : "pause");
|
||||||
|
|
||||||
|
if(model->is_paused) {
|
||||||
|
canvas_draw_icon(canvas, buttons_x + 2, buttons_y + 21, &I_ButtonLeftSmall_3x5);
|
||||||
|
canvas_draw_icon(canvas, buttons_x + 7, buttons_y + 21, &I_ButtonRightSmall_3x5);
|
||||||
|
canvas_draw_str(canvas, buttons_x + 14, buttons_y + 26, "select");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool infrared_progress_view_set_progress(InfraredProgressView* instance, uint16_t progress) {
|
||||||
|
bool result;
|
||||||
|
with_view_model(
|
||||||
|
instance->view,
|
||||||
|
InfraredProgressViewModel * model,
|
||||||
|
{
|
||||||
|
result = progress <= model->progress_total;
|
||||||
|
if(result) model->progress = progress;
|
||||||
|
},
|
||||||
|
true);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void infrared_progress_view_set_progress_total(
|
void infrared_progress_view_set_progress_total(
|
||||||
@@ -74,14 +100,40 @@ void infrared_progress_view_set_progress_total(
|
|||||||
view_commit_model(progress->view, false);
|
view_commit_model(progress->view, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void infrared_progress_view_set_paused(InfraredProgressView* instance, bool is_paused) {
|
||||||
|
with_view_model(
|
||||||
|
instance->view, InfraredProgressViewModel * model, { model->is_paused = is_paused; }, true);
|
||||||
|
}
|
||||||
|
|
||||||
bool infrared_progress_view_input_callback(InputEvent* event, void* context) {
|
bool infrared_progress_view_input_callback(InputEvent* event, void* context) {
|
||||||
InfraredProgressView* instance = context;
|
InfraredProgressView* instance = context;
|
||||||
|
if(event->type != InputTypeShort && event->type != InputTypeRepeat) return false;
|
||||||
|
if(!instance->input_callback) return false;
|
||||||
|
|
||||||
if((event->type == InputTypeShort) && (event->key == InputKeyBack)) {
|
with_view_model(
|
||||||
if(instance->back_callback) {
|
instance->view,
|
||||||
instance->back_callback(instance->context);
|
InfraredProgressViewModel * model,
|
||||||
}
|
{
|
||||||
|
if(model->is_paused) {
|
||||||
|
if(event->key == InputKeyLeft)
|
||||||
|
instance->input_callback(
|
||||||
|
instance->context, InfraredProgressViewInputPreviousSignal);
|
||||||
|
else if(event->key == InputKeyRight)
|
||||||
|
instance->input_callback(
|
||||||
|
instance->context, InfraredProgressViewInputNextSignal);
|
||||||
|
else if(event->key == InputKeyOk)
|
||||||
|
instance->input_callback(
|
||||||
|
instance->context, InfraredProgressViewInputSendSingle);
|
||||||
|
else if(event->key == InputKeyBack)
|
||||||
|
instance->input_callback(instance->context, InfraredProgressViewInputResume);
|
||||||
|
} else {
|
||||||
|
if(event->key == InputKeyOk)
|
||||||
|
instance->input_callback(instance->context, InfraredProgressViewInputPause);
|
||||||
|
else if(event->key == InputKeyBack)
|
||||||
|
instance->input_callback(instance->context, InfraredProgressViewInputStop);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -106,12 +158,12 @@ void infrared_progress_view_free(InfraredProgressView* progress) {
|
|||||||
free(progress);
|
free(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void infrared_progress_view_set_back_callback(
|
void infrared_progress_view_set_input_callback(
|
||||||
InfraredProgressView* instance,
|
InfraredProgressView* instance,
|
||||||
InfraredProgressViewBackCallback callback,
|
InfraredProgressViewInputCallback callback,
|
||||||
void* context) {
|
void* context) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
instance->back_callback = callback;
|
instance->input_callback = callback;
|
||||||
instance->context = context;
|
instance->context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,17 @@ extern "C" {
|
|||||||
/** Anonymous instance */
|
/** Anonymous instance */
|
||||||
typedef struct InfraredProgressView InfraredProgressView;
|
typedef struct InfraredProgressView InfraredProgressView;
|
||||||
|
|
||||||
/** Callback for back button handling */
|
typedef enum {
|
||||||
typedef void (*InfraredProgressViewBackCallback)(void*);
|
InfraredProgressViewInputStop,
|
||||||
|
InfraredProgressViewInputPause,
|
||||||
|
InfraredProgressViewInputResume,
|
||||||
|
InfraredProgressViewInputPreviousSignal,
|
||||||
|
InfraredProgressViewInputNextSignal,
|
||||||
|
InfraredProgressViewInputSendSingle,
|
||||||
|
} InfraredProgressViewInput;
|
||||||
|
|
||||||
|
/** Callback for input handling */
|
||||||
|
typedef void (*InfraredProgressViewInputCallback)(void* context, InfraredProgressViewInput event);
|
||||||
|
|
||||||
/** Allocate and initialize Infrared view
|
/** Allocate and initialize Infrared view
|
||||||
*
|
*
|
||||||
@@ -35,13 +44,12 @@ void infrared_progress_view_free(InfraredProgressView* instance);
|
|||||||
*/
|
*/
|
||||||
View* infrared_progress_view_get_view(InfraredProgressView* instance);
|
View* infrared_progress_view_get_view(InfraredProgressView* instance);
|
||||||
|
|
||||||
/** Increase progress on progress view module
|
/** Set progress of progress view module
|
||||||
*
|
*
|
||||||
* @param instance view module
|
* @param instance view module
|
||||||
* @retval true - value is incremented and maximum is reached,
|
* @param progress progress value
|
||||||
* false - value is incremented and maximum is not reached
|
|
||||||
*/
|
*/
|
||||||
bool infrared_progress_view_increase_progress(InfraredProgressView* instance);
|
bool infrared_progress_view_set_progress(InfraredProgressView* instance, uint16_t progress);
|
||||||
|
|
||||||
/** Set maximum progress value
|
/** Set maximum progress value
|
||||||
*
|
*
|
||||||
@@ -52,15 +60,22 @@ void infrared_progress_view_set_progress_total(
|
|||||||
InfraredProgressView* instance,
|
InfraredProgressView* instance,
|
||||||
uint16_t progress_max);
|
uint16_t progress_max);
|
||||||
|
|
||||||
/** Set back button callback
|
/** Selects the variant of the View
|
||||||
|
*
|
||||||
|
* @param instance view instance
|
||||||
|
* @param is_paused the "paused" variant is displayed if true; the "sending" one if false
|
||||||
|
*/
|
||||||
|
void infrared_progress_view_set_paused(InfraredProgressView* instance, bool is_paused);
|
||||||
|
|
||||||
|
/** Set input callback
|
||||||
*
|
*
|
||||||
* @param instance - view module
|
* @param instance - view module
|
||||||
* @param callback - callback to call for back button
|
* @param callback - callback to call for input
|
||||||
* @param context - context to pass to callback
|
* @param context - context to pass to callback
|
||||||
*/
|
*/
|
||||||
void infrared_progress_view_set_back_callback(
|
void infrared_progress_view_set_input_callback(
|
||||||
InfraredProgressView* instance,
|
InfraredProgressView* instance,
|
||||||
InfraredProgressViewBackCallback callback,
|
InfraredProgressViewInputCallback callback,
|
||||||
void* context);
|
void* context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -230,6 +230,11 @@ bool scene_manager_search_and_switch_to_another_scene(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t scene_manager_get_current_scene(SceneManager* scene_manager) {
|
||||||
|
furi_check(scene_manager);
|
||||||
|
return *SceneManagerIdStack_back(scene_manager->scene_id_stack);
|
||||||
|
}
|
||||||
|
|
||||||
void scene_manager_stop(SceneManager* scene_manager) {
|
void scene_manager_stop(SceneManager* scene_manager) {
|
||||||
furi_check(scene_manager);
|
furi_check(scene_manager);
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,14 @@ bool scene_manager_search_and_switch_to_another_scene(
|
|||||||
SceneManager* scene_manager,
|
SceneManager* scene_manager,
|
||||||
uint32_t scene_id);
|
uint32_t scene_id);
|
||||||
|
|
||||||
|
/** Get id of current scene
|
||||||
|
*
|
||||||
|
* @param scene_manager SceneManager instance
|
||||||
|
*
|
||||||
|
* @return Scene ID
|
||||||
|
*/
|
||||||
|
uint32_t scene_manager_get_current_scene(SceneManager* scene_manager);
|
||||||
|
|
||||||
/** Exit from current scene
|
/** Exit from current scene
|
||||||
*
|
*
|
||||||
* @param scene_manager SceneManager instance
|
* @param scene_manager SceneManager instance
|
||||||
|
|||||||
@@ -193,3 +193,18 @@ ID 1234:abcd Flipper Devices:Flipper Zero
|
|||||||
>
|
>
|
||||||
> VID and PID are hex codes and are mandatory.
|
> VID and PID are hex codes and are mandatory.
|
||||||
> Manufacturer and Product are text strings and are optional.
|
> Manufacturer and Product are text strings and are optional.
|
||||||
|
|
||||||
|
## Mouse Commands
|
||||||
|
|
||||||
|
Mouse movement and click commands. Mouse click commands support HOLD functionality.
|
||||||
|
|
||||||
|
| Command | Parameters | Notes |
|
||||||
|
| ------------- | -------------------------------| -------------------------------- |
|
||||||
|
| LEFTCLICK | None | |
|
||||||
|
| LEFT_CLICK | None | functionally same as LEFTCLICK |
|
||||||
|
| RIGHTCLICK | None | |
|
||||||
|
| RIGHT_CLICK | None | functionally same as RIGHTCLICK |
|
||||||
|
| MOUSEMOVE | x y: int move mount/direction | |
|
||||||
|
| MOUSE_MOVE | x y: int move mount/direction | functionally same as MOUSEMOVE |
|
||||||
|
| MOUSESCROLL | delta: int scroll distance | |
|
||||||
|
| MOUSE_SCROLL | delta: int scroll distance | functionally same as MOUSESCROLL |
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
#include "flipper_format_stream.h"
|
#include "flipper_format_stream.h"
|
||||||
#include "flipper_format_stream_i.h"
|
#include "flipper_format_stream_i.h"
|
||||||
|
|
||||||
|
// permits direct casting between `FlipperFormatOffset` and `StreamOffset`
|
||||||
|
static_assert((size_t)FlipperFormatOffsetFromCurrent == (size_t)StreamOffsetFromCurrent);
|
||||||
|
static_assert((size_t)FlipperFormatOffsetFromStart == (size_t)StreamOffsetFromStart);
|
||||||
|
static_assert((size_t)FlipperFormatOffsetFromEnd == (size_t)StreamOffsetFromEnd);
|
||||||
|
|
||||||
/********************************** Private **********************************/
|
/********************************** Private **********************************/
|
||||||
struct FlipperFormat {
|
struct FlipperFormat {
|
||||||
Stream* stream;
|
Stream* stream;
|
||||||
@@ -127,6 +132,17 @@ bool flipper_format_rewind(FlipperFormat* flipper_format) {
|
|||||||
return stream_rewind(flipper_format->stream);
|
return stream_rewind(flipper_format->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t flipper_format_tell(FlipperFormat* flipper_format) {
|
||||||
|
furi_check(flipper_format);
|
||||||
|
return stream_tell(flipper_format->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool flipper_format_seek(FlipperFormat* flipper_format, int32_t offset, FlipperFormatOffset anchor) {
|
||||||
|
furi_check(flipper_format);
|
||||||
|
// direct usage of `anchor` made valid by `static_assert`s at the top of this file
|
||||||
|
return stream_seek(flipper_format->stream, offset, (StreamOffset)anchor);
|
||||||
|
}
|
||||||
|
|
||||||
bool flipper_format_seek_to_end(FlipperFormat* flipper_format) {
|
bool flipper_format_seek_to_end(FlipperFormat* flipper_format) {
|
||||||
furi_check(flipper_format);
|
furi_check(flipper_format);
|
||||||
return stream_seek(flipper_format->stream, 0, StreamOffsetFromEnd);
|
return stream_seek(flipper_format->stream, 0, StreamOffsetFromEnd);
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ extern "C" {
|
|||||||
|
|
||||||
typedef struct FlipperFormat FlipperFormat;
|
typedef struct FlipperFormat FlipperFormat;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FlipperFormatOffsetFromCurrent,
|
||||||
|
FlipperFormatOffsetFromStart,
|
||||||
|
FlipperFormatOffsetFromEnd,
|
||||||
|
} FlipperFormatOffset;
|
||||||
|
|
||||||
/** Allocate FlipperFormat as string.
|
/** Allocate FlipperFormat as string.
|
||||||
*
|
*
|
||||||
* @return FlipperFormat* pointer to a FlipperFormat instance
|
* @return FlipperFormat* pointer to a FlipperFormat instance
|
||||||
@@ -216,6 +222,24 @@ void flipper_format_set_strict_mode(FlipperFormat* flipper_format, bool strict_m
|
|||||||
*/
|
*/
|
||||||
bool flipper_format_rewind(FlipperFormat* flipper_format);
|
bool flipper_format_rewind(FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/** Get the RW pointer position
|
||||||
|
*
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
*
|
||||||
|
* @return RW pointer position
|
||||||
|
*/
|
||||||
|
size_t flipper_format_tell(FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
/** Set the RW pointer position to an arbitrary value
|
||||||
|
*
|
||||||
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
|
* @param offset Offset relative to the anchor point
|
||||||
|
* @param anchor Anchor point (e.g. start of file)
|
||||||
|
*
|
||||||
|
* @return True on success
|
||||||
|
*/
|
||||||
|
bool flipper_format_seek(FlipperFormat* flipper_format, int32_t offset, FlipperFormatOffset anchor);
|
||||||
|
|
||||||
/** Move the RW pointer at the end. Can be useful if you want to add some data
|
/** Move the RW pointer at the end. Can be useful if you want to add some data
|
||||||
* after reading.
|
* after reading.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ SubGhzProtocolStatus
|
|||||||
res = SubGhzProtocolStatusErrorEncoderGetUpload;
|
res = SubGhzProtocolStatusErrorEncoderGetUpload;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->encoder.is_running = true;
|
instance->encoder.is_running = true;
|
||||||
|
|
||||||
res = SubGhzProtocolStatusOk;
|
res = SubGhzProtocolStatusOk;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"[python]": {
|
"[python]": {
|
||||||
"editor.defaultFormatter": "ms-python.black-formatter"
|
"editor.defaultFormatter": "ms-python.black-formatter"
|
||||||
},
|
},
|
||||||
|
"clangd.checkUpdates": false,
|
||||||
"clangd.path": "@UFBT_TOOLCHAIN_CLANGD@",
|
"clangd.path": "@UFBT_TOOLCHAIN_CLANGD@",
|
||||||
"clangd.arguments": [
|
"clangd.arguments": [
|
||||||
"--query-driver=**/arm-none-eabi-*",
|
"--query-driver=**/arm-none-eabi-*",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,80.1,,
|
Version,+,80.2,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@@ -1038,6 +1038,7 @@ Function,+,flipper_format_read_int32,_Bool,"FlipperFormat*, const char*, int32_t
|
|||||||
Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, FuriString*"
|
Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, FuriString*"
|
||||||
Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t"
|
Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t"
|
||||||
Function,+,flipper_format_rewind,_Bool,FlipperFormat*
|
Function,+,flipper_format_rewind,_Bool,FlipperFormat*
|
||||||
|
Function,+,flipper_format_seek,_Bool,"FlipperFormat*, int32_t, FlipperFormatOffset"
|
||||||
Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat*
|
Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat*
|
||||||
Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool"
|
Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool"
|
||||||
Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool"
|
Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool"
|
||||||
@@ -1046,6 +1047,7 @@ Function,+,flipper_format_stream_read_value_line,_Bool,"Stream*, const char*, Fl
|
|||||||
Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*"
|
Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*"
|
||||||
Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*"
|
Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*"
|
||||||
Function,+,flipper_format_string_alloc,FlipperFormat*,
|
Function,+,flipper_format_string_alloc,FlipperFormat*,
|
||||||
|
Function,+,flipper_format_tell,size_t,FlipperFormat*
|
||||||
Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
||||||
Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
||||||
Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t"
|
Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t"
|
||||||
@@ -2469,6 +2471,7 @@ Function,-,scalbnl,long double,"long double, int"
|
|||||||
Function,-,scanf,int,"const char*, ..."
|
Function,-,scanf,int,"const char*, ..."
|
||||||
Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*"
|
Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*"
|
||||||
Function,+,scene_manager_free,void,SceneManager*
|
Function,+,scene_manager_free,void,SceneManager*
|
||||||
|
Function,+,scene_manager_get_current_scene,uint32_t,SceneManager*
|
||||||
Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t"
|
Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t"
|
||||||
Function,+,scene_manager_handle_back_event,_Bool,SceneManager*
|
Function,+,scene_manager_handle_back_event,_Bool,SceneManager*
|
||||||
Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t"
|
Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t"
|
||||||
|
|||||||
|
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,80.1,,
|
Version,+,80.2,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
@@ -1179,6 +1179,7 @@ Function,+,flipper_format_read_int32,_Bool,"FlipperFormat*, const char*, int32_t
|
|||||||
Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, FuriString*"
|
Function,+,flipper_format_read_string,_Bool,"FlipperFormat*, const char*, FuriString*"
|
||||||
Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t"
|
Function,+,flipper_format_read_uint32,_Bool,"FlipperFormat*, const char*, uint32_t*, const uint16_t"
|
||||||
Function,+,flipper_format_rewind,_Bool,FlipperFormat*
|
Function,+,flipper_format_rewind,_Bool,FlipperFormat*
|
||||||
|
Function,+,flipper_format_seek,_Bool,"FlipperFormat*, int32_t, FlipperFormatOffset"
|
||||||
Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat*
|
Function,+,flipper_format_seek_to_end,_Bool,FlipperFormat*
|
||||||
Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool"
|
Function,+,flipper_format_set_strict_mode,void,"FlipperFormat*, _Bool"
|
||||||
Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool"
|
Function,+,flipper_format_stream_delete_key_and_write,_Bool,"Stream*, FlipperStreamWriteData*, _Bool"
|
||||||
@@ -1187,6 +1188,7 @@ Function,+,flipper_format_stream_read_value_line,_Bool,"Stream*, const char*, Fl
|
|||||||
Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*"
|
Function,+,flipper_format_stream_write_comment_cstr,_Bool,"Stream*, const char*"
|
||||||
Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*"
|
Function,+,flipper_format_stream_write_value_line,_Bool,"Stream*, FlipperStreamWriteData*"
|
||||||
Function,+,flipper_format_string_alloc,FlipperFormat*,
|
Function,+,flipper_format_string_alloc,FlipperFormat*,
|
||||||
|
Function,+,flipper_format_tell,size_t,FlipperFormat*
|
||||||
Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
Function,+,flipper_format_update_bool,_Bool,"FlipperFormat*, const char*, const _Bool*, const uint16_t"
|
||||||
Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
Function,+,flipper_format_update_float,_Bool,"FlipperFormat*, const char*, const float*, const uint16_t"
|
||||||
Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t"
|
Function,+,flipper_format_update_hex,_Bool,"FlipperFormat*, const char*, const uint8_t*, const uint16_t"
|
||||||
@@ -3167,6 +3169,7 @@ Function,-,scalbnl,long double,"long double, int"
|
|||||||
Function,-,scanf,int,"const char*, ..."
|
Function,-,scanf,int,"const char*, ..."
|
||||||
Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*"
|
Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*"
|
||||||
Function,+,scene_manager_free,void,SceneManager*
|
Function,+,scene_manager_free,void,SceneManager*
|
||||||
|
Function,+,scene_manager_get_current_scene,uint32_t,SceneManager*
|
||||||
Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t"
|
Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t"
|
||||||
Function,+,scene_manager_handle_back_event,_Bool,SceneManager*
|
Function,+,scene_manager_handle_back_event,_Bool,SceneManager*
|
||||||
Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t"
|
Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t"
|
||||||
|
|||||||
|
Reference in New Issue
Block a user