Move most Bad BLE code to Bad USB
@@ -1,18 +0,0 @@
|
||||
App(
|
||||
appid="bad_ble",
|
||||
name="Bad BLE",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="bad_ble_app",
|
||||
cdefines=["APP_BAD_BLE"],
|
||||
requires=[
|
||||
"gui",
|
||||
"dialogs",
|
||||
],
|
||||
stack_size=2 * 1024,
|
||||
# icon="A_BadUsb_14",
|
||||
order=70,
|
||||
fap_category="Main",
|
||||
fap_icon="badusb_10px.png",
|
||||
fap_icon_assets="images",
|
||||
fap_libs=["assets"],
|
||||
)
|
||||
@@ -1,194 +0,0 @@
|
||||
#include "bad_ble_app_i.h"
|
||||
#include "bad_ble_settings_filename.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include <bt/bt_service/bt_i.h>
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#define BAD_BLE_SETTINGS_PATH BAD_BLE_APP_BASE_FOLDER "/" BAD_BLE_SETTINGS_FILE_NAME
|
||||
|
||||
static bool bad_ble_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
BadBleApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool bad_ble_app_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
BadBleApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void bad_ble_app_tick_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
BadBleApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void bad_ble_load_settings(BadBleApp* app) {
|
||||
File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
if(storage_file_open(settings_file, BAD_BLE_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
char chr;
|
||||
while((storage_file_read(settings_file, &chr, 1) == 1) &&
|
||||
!storage_file_eof(settings_file) && !isspace(chr)) {
|
||||
furi_string_push_back(app->keyboard_layout, chr);
|
||||
}
|
||||
}
|
||||
storage_file_close(settings_file);
|
||||
storage_file_free(settings_file);
|
||||
}
|
||||
|
||||
static void bad_ble_save_settings(BadBleApp* app) {
|
||||
File* settings_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
if(storage_file_open(settings_file, BAD_BLE_SETTINGS_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS)) {
|
||||
storage_file_write(
|
||||
settings_file,
|
||||
furi_string_get_cstr(app->keyboard_layout),
|
||||
furi_string_size(app->keyboard_layout));
|
||||
storage_file_write(settings_file, "\n", 1);
|
||||
}
|
||||
storage_file_close(settings_file);
|
||||
storage_file_free(settings_file);
|
||||
}
|
||||
|
||||
void bad_ble_set_name(BadBleApp* app, const char* fmt, ...) {
|
||||
furi_assert(app);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(app->name, BAD_BLE_ADV_NAME_MAX_LEN, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
BadBleApp* bad_ble_app_alloc(char* arg) {
|
||||
BadBleApp* app = malloc(sizeof(BadBleApp));
|
||||
|
||||
app->bad_ble_script = NULL;
|
||||
|
||||
app->file_path = furi_string_alloc();
|
||||
app->keyboard_layout = furi_string_alloc();
|
||||
if(arg && strlen(arg)) {
|
||||
furi_string_set(app->file_path, arg);
|
||||
}
|
||||
|
||||
bad_ble_load_settings(app);
|
||||
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
app->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
app->scene_manager = scene_manager_alloc(&bad_ble_scene_handlers, app);
|
||||
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, bad_ble_app_tick_event_callback, 500);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, bad_ble_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, bad_ble_app_back_event_callback);
|
||||
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
app->bt = bt;
|
||||
const char* adv_name = bt_get_profile_adv_name(bt);
|
||||
memcpy(app->name, adv_name, BAD_BLE_ADV_NAME_MAX_LEN);
|
||||
|
||||
const uint8_t* mac_addr = bt_get_profile_mac_address(bt);
|
||||
memcpy(app->mac, mac_addr, BAD_BLE_MAC_ADDRESS_LEN);
|
||||
|
||||
// Custom Widget
|
||||
app->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadBleAppViewError, widget_get_view(app->widget));
|
||||
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadBleAppViewConfig, submenu_get_view(app->submenu));
|
||||
|
||||
app->bad_ble_view = bad_ble_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadBleAppViewWork, bad_ble_get_view(app->bad_ble_view));
|
||||
|
||||
app->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadBleAppViewConfigName, text_input_get_view(app->text_input));
|
||||
|
||||
app->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadBleAppViewConfigMac, byte_input_get_view(app->byte_input));
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
if(!furi_string_empty(app->file_path)) {
|
||||
app->bad_ble_script = bad_ble_script_open(app->file_path, bt);
|
||||
bad_ble_script_set_keyboard_layout(app->bad_ble_script, app->keyboard_layout);
|
||||
scene_manager_next_scene(app->scene_manager, BadBleSceneWork);
|
||||
} else {
|
||||
furi_string_set(app->file_path, BAD_BLE_APP_BASE_FOLDER);
|
||||
scene_manager_next_scene(app->scene_manager, BadBleSceneFileSelect);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void bad_ble_app_free(BadBleApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
if(app->bad_ble_script) {
|
||||
bad_ble_script_close(app->bad_ble_script);
|
||||
app->bad_ble_script = NULL;
|
||||
}
|
||||
|
||||
// Views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewWork);
|
||||
bad_ble_free(app->bad_ble_view);
|
||||
|
||||
// Custom Widget
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewError);
|
||||
widget_free(app->widget);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewConfig);
|
||||
submenu_free(app->submenu);
|
||||
|
||||
// Text Input
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewConfigName);
|
||||
text_input_free(app->text_input);
|
||||
|
||||
// Byte Input
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewConfigMac);
|
||||
byte_input_free(app->byte_input);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
furi_record_close(RECORD_BT);
|
||||
|
||||
bad_ble_save_settings(app);
|
||||
|
||||
furi_string_free(app->file_path);
|
||||
furi_string_free(app->keyboard_layout);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t bad_ble_app(void* p) {
|
||||
BadBleApp* bad_ble_app = bad_ble_app_alloc((char*)p);
|
||||
|
||||
view_dispatcher_run(bad_ble_app->view_dispatcher);
|
||||
|
||||
bad_ble_app_free(bad_ble_app);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct BadBleApp BadBleApp;
|
||||
|
||||
void bad_ble_set_name(BadBleApp* app, const char* fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "bad_ble_app.h"
|
||||
#include "scenes/bad_ble_scene.h"
|
||||
#include "bad_ble_script.h"
|
||||
#include "bad_ble_custom_event.h"
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <bad_ble_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include "views/bad_ble_view.h"
|
||||
|
||||
#define BAD_BLE_APP_BASE_FOLDER ANY_PATH("BadUsb")
|
||||
#define BAD_BLE_APP_PATH_LAYOUT_FOLDER BAD_BLE_APP_BASE_FOLDER "/layouts"
|
||||
#define BAD_BLE_APP_SCRIPT_EXTENSION ".txt"
|
||||
#define BAD_BLE_APP_LAYOUT_EXTENSION ".kl"
|
||||
|
||||
#define BAD_BLE_MAC_ADDRESS_LEN 6 // need replace with MAC size maccro
|
||||
#define BAD_BLE_ADV_NAME_MAX_LEN 18
|
||||
|
||||
typedef enum {
|
||||
BadBleAppErrorNoFiles,
|
||||
BadBleAppErrorCloseRpc,
|
||||
} BadBleAppError;
|
||||
|
||||
struct BadBleApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
Widget* widget;
|
||||
Submenu* submenu;
|
||||
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
uint8_t mac[BAD_BLE_MAC_ADDRESS_LEN];
|
||||
char name[BAD_BLE_ADV_NAME_MAX_LEN + 1];
|
||||
|
||||
BadBleAppError error;
|
||||
FuriString* file_path;
|
||||
FuriString* keyboard_layout;
|
||||
BadBle* bad_ble_view;
|
||||
BadBleScript* bad_ble_script;
|
||||
|
||||
Bt* bt;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BadBleAppViewError,
|
||||
BadBleAppViewWork,
|
||||
BadBleAppViewConfig,
|
||||
BadBleAppViewConfigMac,
|
||||
BadBleAppViewConfigName
|
||||
} BadBleAppView;
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
typedef enum BadBleCustomEvent {
|
||||
BadBleAppCustomEventTextEditResult,
|
||||
BadBleAppCustomEventByteInputDone,
|
||||
BadBleCustomEventErrorBack
|
||||
} BadBleCustomEvent;
|
||||
@@ -1,198 +1,199 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
#include <lib/toolbox/args.h>
|
||||
#include <furi_hal_bt_hid.h>
|
||||
#include <storage/storage.h>
|
||||
#include "bad_ble_script.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
// #include <furi.h>
|
||||
// #include <furi_hal.h>
|
||||
// #include <gui/gui.h>
|
||||
// #include <input/input.h>
|
||||
// #include <lib/toolbox/args.h>
|
||||
// #include <furi_hal_bt_hid.h>
|
||||
|
||||
#include <bt/bt_service/bt.h>
|
||||
// #include <storage/storage.h>
|
||||
// #include "bad_ble_script.h"
|
||||
// #include <dolphin/dolphin.h>
|
||||
|
||||
#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys")
|
||||
// #include <bt/bt_service/bt.h>
|
||||
|
||||
#define TAG "BadBle"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
#define FILE_BUFFER_LEN 16
|
||||
// #define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys")
|
||||
|
||||
#define SCRIPT_STATE_ERROR (-1)
|
||||
#define SCRIPT_STATE_END (-2)
|
||||
#define SCRIPT_STATE_NEXT_LINE (-3)
|
||||
// #define TAG "BadBle"
|
||||
// #define WORKER_TAG TAG "Worker"
|
||||
// #define FILE_BUFFER_LEN 16
|
||||
|
||||
#define BADBLE_ASCII_TO_KEY(script, x) \
|
||||
(((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
|
||||
// #define SCRIPT_STATE_ERROR (-1)
|
||||
// #define SCRIPT_STATE_END (-2)
|
||||
// #define SCRIPT_STATE_NEXT_LINE (-3)
|
||||
|
||||
typedef enum {
|
||||
WorkerEvtToggle = (1 << 0),
|
||||
WorkerEvtEnd = (1 << 1),
|
||||
WorkerEvtConnect = (1 << 2),
|
||||
WorkerEvtDisconnect = (1 << 3),
|
||||
} WorkerEvtFlags;
|
||||
// #define BADBLE_ASCII_TO_KEY(script, x) \
|
||||
// (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE)
|
||||
|
||||
typedef enum {
|
||||
LevelRssi122_100,
|
||||
LevelRssi99_80,
|
||||
LevelRssi79_60,
|
||||
LevelRssi59_40,
|
||||
LevelRssi39_0,
|
||||
LevelRssiNum,
|
||||
LevelRssiError = 0xFF,
|
||||
} LevelRssiRange;
|
||||
// typedef enum {
|
||||
// WorkerEvtToggle = (1 << 0),
|
||||
// WorkerEvtEnd = (1 << 1),
|
||||
// WorkerEvtConnect = (1 << 2),
|
||||
// WorkerEvtDisconnect = (1 << 3),
|
||||
// } WorkerEvtFlags;
|
||||
|
||||
/**
|
||||
* Delays for waiting between HID key press and key release
|
||||
*/
|
||||
const uint8_t bt_hid_delays[LevelRssiNum] = {
|
||||
30, // LevelRssi122_100
|
||||
25, // LevelRssi99_80
|
||||
20, // LevelRssi79_60
|
||||
17, // LevelRssi59_40
|
||||
14, // LevelRssi39_0
|
||||
};
|
||||
// typedef enum {
|
||||
// LevelRssi122_100,
|
||||
// LevelRssi99_80,
|
||||
// LevelRssi79_60,
|
||||
// LevelRssi59_40,
|
||||
// LevelRssi39_0,
|
||||
// LevelRssiNum,
|
||||
// LevelRssiError = 0xFF,
|
||||
// } LevelRssiRange;
|
||||
|
||||
struct BadBleScript {
|
||||
BadBleState st;
|
||||
FuriString* file_path;
|
||||
uint32_t defdelay;
|
||||
uint16_t layout[128];
|
||||
FuriThread* thread;
|
||||
uint8_t file_buf[FILE_BUFFER_LEN + 1];
|
||||
uint8_t buf_start;
|
||||
uint8_t buf_len;
|
||||
bool file_end;
|
||||
FuriString* line;
|
||||
// /**
|
||||
// * Delays for waiting between HID key press and key release
|
||||
// */
|
||||
// const uint8_t bt_hid_delays[LevelRssiNum] = {
|
||||
// 30, // LevelRssi122_100
|
||||
// 25, // LevelRssi99_80
|
||||
// 20, // LevelRssi79_60
|
||||
// 17, // LevelRssi59_40
|
||||
// 14, // LevelRssi39_0
|
||||
// };
|
||||
|
||||
FuriString* line_prev;
|
||||
uint32_t repeat_cnt;
|
||||
// struct BadBleScript {
|
||||
|
||||
File* debug_file;
|
||||
Bt* bt;
|
||||
};
|
||||
// BadBleState st;
|
||||
// FuriString* file_path;
|
||||
// uint32_t defdelay;
|
||||
// uint16_t layout[128];
|
||||
// FuriThread* thread;
|
||||
// uint8_t file_buf[FILE_BUFFER_LEN + 1];
|
||||
// uint8_t buf_start;
|
||||
// uint8_t buf_len;
|
||||
// bool file_end;
|
||||
// FuriString* line;
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
uint16_t keycode;
|
||||
} DuckyKey;
|
||||
// FuriString* line_prev;
|
||||
// uint32_t repeat_cnt;
|
||||
|
||||
static const DuckyKey ducky_keys[] = {
|
||||
{"CTRL-ALT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_ALT},
|
||||
{"CTRL-SHIFT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT},
|
||||
{"ALT-SHIFT", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_SHIFT},
|
||||
{"ALT-GUI", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_GUI},
|
||||
{"GUI-SHIFT", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT},
|
||||
// Bt* bt;
|
||||
// };
|
||||
|
||||
{"CTRL", KEY_MOD_LEFT_CTRL},
|
||||
{"CONTROL", KEY_MOD_LEFT_CTRL},
|
||||
{"SHIFT", KEY_MOD_LEFT_SHIFT},
|
||||
{"ALT", KEY_MOD_LEFT_ALT},
|
||||
{"GUI", KEY_MOD_LEFT_GUI},
|
||||
{"WINDOWS", KEY_MOD_LEFT_GUI},
|
||||
// typedef struct {
|
||||
// char* name;
|
||||
// uint16_t keycode;
|
||||
// } DuckyKey;
|
||||
|
||||
{"DOWNARROW", HID_KEYBOARD_DOWN_ARROW},
|
||||
{"DOWN", HID_KEYBOARD_DOWN_ARROW},
|
||||
{"LEFTARROW", HID_KEYBOARD_LEFT_ARROW},
|
||||
{"LEFT", HID_KEYBOARD_LEFT_ARROW},
|
||||
{"RIGHTARROW", HID_KEYBOARD_RIGHT_ARROW},
|
||||
{"RIGHT", HID_KEYBOARD_RIGHT_ARROW},
|
||||
{"UPARROW", HID_KEYBOARD_UP_ARROW},
|
||||
{"UP", HID_KEYBOARD_UP_ARROW},
|
||||
// static const DuckyKey ducky_keys[] = {
|
||||
// {"CTRL-ALT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_ALT},
|
||||
// {"CTRL-SHIFT", KEY_MOD_LEFT_CTRL | KEY_MOD_LEFT_SHIFT},
|
||||
// {"ALT-SHIFT", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_SHIFT},
|
||||
// {"ALT-GUI", KEY_MOD_LEFT_ALT | KEY_MOD_LEFT_GUI},
|
||||
// {"GUI-SHIFT", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_SHIFT},
|
||||
|
||||
{"ENTER", HID_KEYBOARD_RETURN},
|
||||
{"BREAK", HID_KEYBOARD_PAUSE},
|
||||
{"PAUSE", HID_KEYBOARD_PAUSE},
|
||||
{"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
|
||||
{"DELETE", HID_KEYBOARD_DELETE},
|
||||
{"BACKSPACE", HID_KEYPAD_BACKSPACE},
|
||||
{"END", HID_KEYBOARD_END},
|
||||
{"ESC", HID_KEYBOARD_ESCAPE},
|
||||
{"ESCAPE", HID_KEYBOARD_ESCAPE},
|
||||
{"HOME", HID_KEYBOARD_HOME},
|
||||
{"INSERT", HID_KEYBOARD_INSERT},
|
||||
{"NUMLOCK", HID_KEYPAD_NUMLOCK},
|
||||
{"PAGEUP", HID_KEYBOARD_PAGE_UP},
|
||||
{"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN},
|
||||
{"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN},
|
||||
{"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
{"SPACE", HID_KEYBOARD_SPACEBAR},
|
||||
{"TAB", HID_KEYBOARD_TAB},
|
||||
{"MENU", HID_KEYBOARD_APPLICATION},
|
||||
{"APP", HID_KEYBOARD_APPLICATION},
|
||||
// {"CTRL", KEY_MOD_LEFT_CTRL},
|
||||
// {"CONTROL", KEY_MOD_LEFT_CTRL},
|
||||
// {"SHIFT", KEY_MOD_LEFT_SHIFT},
|
||||
// {"ALT", KEY_MOD_LEFT_ALT},
|
||||
// {"GUI", KEY_MOD_LEFT_GUI},
|
||||
// {"WINDOWS", KEY_MOD_LEFT_GUI},
|
||||
|
||||
{"F1", HID_KEYBOARD_F1},
|
||||
{"F2", HID_KEYBOARD_F2},
|
||||
{"F3", HID_KEYBOARD_F3},
|
||||
{"F4", HID_KEYBOARD_F4},
|
||||
{"F5", HID_KEYBOARD_F5},
|
||||
{"F6", HID_KEYBOARD_F6},
|
||||
{"F7", HID_KEYBOARD_F7},
|
||||
{"F8", HID_KEYBOARD_F8},
|
||||
{"F9", HID_KEYBOARD_F9},
|
||||
{"F10", HID_KEYBOARD_F10},
|
||||
{"F11", HID_KEYBOARD_F11},
|
||||
{"F12", HID_KEYBOARD_F12},
|
||||
};
|
||||
// {"DOWNARROW", HID_KEYBOARD_DOWN_ARROW},
|
||||
// {"DOWN", HID_KEYBOARD_DOWN_ARROW},
|
||||
// {"LEFTARROW", HID_KEYBOARD_LEFT_ARROW},
|
||||
// {"LEFT", HID_KEYBOARD_LEFT_ARROW},
|
||||
// {"RIGHTARROW", HID_KEYBOARD_RIGHT_ARROW},
|
||||
// {"RIGHT", HID_KEYBOARD_RIGHT_ARROW},
|
||||
// {"UPARROW", HID_KEYBOARD_UP_ARROW},
|
||||
// {"UP", HID_KEYBOARD_UP_ARROW},
|
||||
|
||||
static const char ducky_cmd_comment[] = {"REM"};
|
||||
static const char ducky_cmd_id[] = {"ID"};
|
||||
static const char ducky_cmd_delay[] = {"DELAY "};
|
||||
static const char ducky_cmd_string[] = {"STRING "};
|
||||
static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
|
||||
static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
|
||||
static const char ducky_cmd_repeat[] = {"REPEAT "};
|
||||
static const char ducky_cmd_sysrq[] = {"SYSRQ "};
|
||||
// {"ENTER", HID_KEYBOARD_RETURN},
|
||||
// {"BREAK", HID_KEYBOARD_PAUSE},
|
||||
// {"PAUSE", HID_KEYBOARD_PAUSE},
|
||||
// {"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
|
||||
// {"DELETE", HID_KEYBOARD_DELETE},
|
||||
// {"BACKSPACE", HID_KEYPAD_BACKSPACE},
|
||||
// {"END", HID_KEYBOARD_END},
|
||||
// {"ESC", HID_KEYBOARD_ESCAPE},
|
||||
// {"ESCAPE", HID_KEYBOARD_ESCAPE},
|
||||
// {"HOME", HID_KEYBOARD_HOME},
|
||||
// {"INSERT", HID_KEYBOARD_INSERT},
|
||||
// {"NUMLOCK", HID_KEYPAD_NUMLOCK},
|
||||
// {"PAGEUP", HID_KEYBOARD_PAGE_UP},
|
||||
// {"PAGEDOWN", HID_KEYBOARD_PAGE_DOWN},
|
||||
// {"PRINTSCREEN", HID_KEYBOARD_PRINT_SCREEN},
|
||||
// {"SCROLLLOCK", HID_KEYBOARD_SCROLL_LOCK},
|
||||
// {"SPACE", HID_KEYBOARD_SPACEBAR},
|
||||
// {"TAB", HID_KEYBOARD_TAB},
|
||||
// {"MENU", HID_KEYBOARD_APPLICATION},
|
||||
// {"APP", HID_KEYBOARD_APPLICATION},
|
||||
|
||||
static const char ducky_cmd_altchar[] = {"ALTCHAR "};
|
||||
static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
|
||||
static const char ducky_cmd_altstr_2[] = {"ALTCODE "};
|
||||
// {"F1", HID_KEYBOARD_F1},
|
||||
// {"F2", HID_KEYBOARD_F2},
|
||||
// {"F3", HID_KEYBOARD_F3},
|
||||
// {"F4", HID_KEYBOARD_F4},
|
||||
// {"F5", HID_KEYBOARD_F5},
|
||||
// {"F6", HID_KEYBOARD_F6},
|
||||
// {"F7", HID_KEYBOARD_F7},
|
||||
// {"F8", HID_KEYBOARD_F8},
|
||||
// {"F9", HID_KEYBOARD_F9},
|
||||
// {"F10", HID_KEYBOARD_F10},
|
||||
// {"F11", HID_KEYBOARD_F11},
|
||||
// {"F12", HID_KEYBOARD_F12},
|
||||
// };
|
||||
|
||||
static const char ducky_cmd_lang[] = {"DUCKY_LANG"};
|
||||
// static const char ducky_cmd_comment[] = {"REM"};
|
||||
// static const char ducky_cmd_id[] = {"ID"};
|
||||
// static const char ducky_cmd_delay[] = {"DELAY "};
|
||||
// static const char ducky_cmd_string[] = {"STRING "};
|
||||
// static const char ducky_cmd_defdelay_1[] = {"DEFAULT_DELAY "};
|
||||
// static const char ducky_cmd_defdelay_2[] = {"DEFAULTDELAY "};
|
||||
// static const char ducky_cmd_repeat[] = {"REPEAT "};
|
||||
// static const char ducky_cmd_sysrq[] = {"SYSRQ "};
|
||||
|
||||
static const uint8_t numpad_keys[10] = {
|
||||
HID_KEYPAD_0,
|
||||
HID_KEYPAD_1,
|
||||
HID_KEYPAD_2,
|
||||
HID_KEYPAD_3,
|
||||
HID_KEYPAD_4,
|
||||
HID_KEYPAD_5,
|
||||
HID_KEYPAD_6,
|
||||
HID_KEYPAD_7,
|
||||
HID_KEYPAD_8,
|
||||
HID_KEYPAD_9,
|
||||
};
|
||||
// static const char ducky_cmd_altchar[] = {"ALTCHAR "};
|
||||
// static const char ducky_cmd_altstr_1[] = {"ALTSTRING "};
|
||||
// static const char ducky_cmd_altstr_2[] = {"ALTCODE "};
|
||||
|
||||
uint8_t bt_timeout = 0;
|
||||
// static const char ducky_cmd_lang[] = {"DUCKY_LANG"};
|
||||
|
||||
static LevelRssiRange bt_remote_rssi_range(Bt* bt) {
|
||||
BtRssi rssi_data = {0};
|
||||
// static const uint8_t numpad_keys[10] = {
|
||||
// HID_KEYPAD_0,
|
||||
// HID_KEYPAD_1,
|
||||
// HID_KEYPAD_2,
|
||||
// HID_KEYPAD_3,
|
||||
// HID_KEYPAD_4,
|
||||
// HID_KEYPAD_5,
|
||||
// HID_KEYPAD_6,
|
||||
// HID_KEYPAD_7,
|
||||
// HID_KEYPAD_8,
|
||||
// HID_KEYPAD_9,
|
||||
// };
|
||||
|
||||
if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError;
|
||||
// uint8_t bt_timeout = 0;
|
||||
|
||||
if(rssi_data.rssi <= 39)
|
||||
return LevelRssi39_0;
|
||||
else if(rssi_data.rssi <= 59)
|
||||
return LevelRssi59_40;
|
||||
else if(rssi_data.rssi <= 79)
|
||||
return LevelRssi79_60;
|
||||
else if(rssi_data.rssi <= 99)
|
||||
return LevelRssi99_80;
|
||||
else if(rssi_data.rssi <= 122)
|
||||
return LevelRssi122_100;
|
||||
// static LevelRssiRange bt_remote_rssi_range(Bt* bt) {
|
||||
// BtRssi rssi_data = {0};
|
||||
|
||||
return LevelRssiError;
|
||||
}
|
||||
// if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError;
|
||||
|
||||
static inline void update_bt_timeout(Bt* bt) {
|
||||
LevelRssiRange r = bt_remote_rssi_range(bt);
|
||||
if(r < LevelRssiNum) {
|
||||
bt_timeout = bt_hid_delays[r];
|
||||
}
|
||||
}
|
||||
// if(rssi_data.rssi <= 39)
|
||||
// return LevelRssi39_0;
|
||||
// else if(rssi_data.rssi <= 59)
|
||||
// return LevelRssi59_40;
|
||||
// else if(rssi_data.rssi <= 79)
|
||||
// return LevelRssi79_60;
|
||||
// else if(rssi_data.rssi <= 99)
|
||||
// return LevelRssi99_80;
|
||||
// else if(rssi_data.rssi <= 122)
|
||||
// return LevelRssi122_100;
|
||||
|
||||
// return LevelRssiError;
|
||||
// }
|
||||
|
||||
// static inline void update_bt_timeout(Bt* bt) {
|
||||
// LevelRssiRange r = bt_remote_rssi_range(bt);
|
||||
// if(r < LevelRssiNum) {
|
||||
// bt_timeout = bt_hid_delays[r];
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @brief Wait until there are enough free slots in the keyboard buffer
|
||||
*
|
||||
* @param n_free_chars Number of free slots to wait for (and consider the buffer not full)
|
||||
*
|
||||
* @param n_free_chars Number of free slots to wait for (and consider the buffer not full)
|
||||
*/
|
||||
static void bt_hid_hold_while_keyboard_buffer_full(uint8_t n_free_chars, int32_t timeout) {
|
||||
uint32_t start = furi_get_tick();
|
||||
@@ -206,26 +207,26 @@ static void bt_hid_hold_while_keyboard_buffer_full(uint8_t n_free_chars, int32_t
|
||||
}
|
||||
}
|
||||
|
||||
static bool ducky_get_number(const char* param, uint32_t* val) {
|
||||
uint32_t value = 0;
|
||||
if(sscanf(param, "%lu", &value) == 1) {
|
||||
*val = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// static bool ducky_get_number(const char* param, uint32_t* val) {
|
||||
// uint32_t value = 0;
|
||||
// if(sscanf(param, "%lu", &value) == 1) {
|
||||
// *val = value;
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
static uint32_t ducky_get_command_len(const char* line) {
|
||||
uint32_t len = strlen(line);
|
||||
for(uint32_t i = 0; i < len; i++) {
|
||||
if(line[i] == ' ') return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// static uint32_t ducky_get_command_len(const char* line) {
|
||||
// uint32_t len = strlen(line);
|
||||
// for(uint32_t i = 0; i < len; i++) {
|
||||
// if(line[i] == ' ') return i;
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
static bool ducky_is_line_end(const char chr) {
|
||||
return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n'));
|
||||
}
|
||||
// static bool ducky_is_line_end(const char chr) {
|
||||
// return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n'));
|
||||
// }
|
||||
|
||||
static void ducky_numlock_on() {
|
||||
if((furi_hal_hid_get_led_state() & HID_KB_LED_NUM) == 0) {
|
||||
@@ -269,25 +270,25 @@ static bool ducky_altchar(const char* charcode) {
|
||||
return state;
|
||||
}
|
||||
|
||||
static bool ducky_altstring(const char* param) {
|
||||
uint32_t i = 0;
|
||||
bool state = false;
|
||||
// static bool ducky_altstring(const char* param) {
|
||||
// uint32_t i = 0;
|
||||
// bool state = false;
|
||||
|
||||
while(param[i] != '\0') {
|
||||
if((param[i] < ' ') || (param[i] > '~')) {
|
||||
i++;
|
||||
continue; // Skip non-printable chars
|
||||
}
|
||||
// while(param[i] != '\0') {
|
||||
// if((param[i] < ' ') || (param[i] > '~')) {
|
||||
// i++;
|
||||
// continue; // Skip non-printable chars
|
||||
// }
|
||||
|
||||
char temp_str[4];
|
||||
snprintf(temp_str, 4, "%u", param[i]);
|
||||
// char temp_str[4];
|
||||
// snprintf(temp_str, 4, "%u", param[i]);
|
||||
|
||||
state = ducky_altchar(temp_str);
|
||||
if(state == false) break;
|
||||
i++;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
// state = ducky_altchar(temp_str);
|
||||
// if(state == false) break;
|
||||
// i++;
|
||||
// }
|
||||
// return state;
|
||||
// }
|
||||
|
||||
static bool ducky_string(BadBleScript* bad_ble, const char* param) {
|
||||
uint32_t i = 0;
|
||||
@@ -305,19 +306,19 @@ static bool ducky_string(BadBleScript* bad_ble, const char* param) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint16_t ducky_get_keycode(BadBleScript* bad_ble, const char* param, bool accept_chars) {
|
||||
for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) {
|
||||
size_t key_cmd_len = strlen(ducky_keys[i].name);
|
||||
if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) &&
|
||||
(ducky_is_line_end(param[key_cmd_len]))) {
|
||||
return ducky_keys[i].keycode;
|
||||
}
|
||||
}
|
||||
if((accept_chars) && (strlen(param) > 0)) {
|
||||
return (BADBLE_ASCII_TO_KEY(bad_ble, param[0]) & 0xFF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// static uint16_t ducky_get_keycode(BadBleScript* bad_ble, const char* param, bool accept_chars) {
|
||||
// for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) {
|
||||
// size_t key_cmd_len = strlen(ducky_keys[i].name);
|
||||
// if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) &&
|
||||
// (ducky_is_line_end(param[key_cmd_len]))) {
|
||||
// return ducky_keys[i].keycode;
|
||||
// }
|
||||
// }
|
||||
// if((accept_chars) && (strlen(param) > 0)) {
|
||||
// return (BADBLE_ASCII_TO_KEY(bad_ble, param[0]) & 0xFF);
|
||||
// }
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
static int32_t
|
||||
ducky_parse_line(BadBleScript* bad_ble, FuriString* line, char* error, size_t error_len) {
|
||||
@@ -749,70 +750,70 @@ static int32_t bad_ble_worker(void* context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bad_ble_script_set_default_keyboard_layout(BadBleScript* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
memset(bad_ble->layout, HID_KEYBOARD_NONE, sizeof(bad_ble->layout));
|
||||
memcpy(bad_ble->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_ble->layout)));
|
||||
}
|
||||
// static void bad_ble_script_set_default_keyboard_layout(BadBleScript* bad_ble) {
|
||||
// furi_assert(bad_ble);
|
||||
// memset(bad_ble->layout, HID_KEYBOARD_NONE, sizeof(bad_ble->layout));
|
||||
// memcpy(bad_ble->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_ble->layout)));
|
||||
// }
|
||||
|
||||
BadBleScript* bad_ble_script_open(FuriString* file_path, Bt* bt) {
|
||||
furi_assert(file_path);
|
||||
// BadBleScript* bad_ble_script_open(FuriString* file_path, Bt* bt) {
|
||||
// furi_assert(file_path);
|
||||
|
||||
BadBleScript* bad_ble = malloc(sizeof(BadBleScript));
|
||||
bad_ble->file_path = furi_string_alloc();
|
||||
furi_string_set(bad_ble->file_path, file_path);
|
||||
bad_ble_script_set_default_keyboard_layout(bad_ble);
|
||||
// BadBleScript* bad_ble = malloc(sizeof(BadBleScript));
|
||||
// bad_ble->file_path = furi_string_alloc();
|
||||
// furi_string_set(bad_ble->file_path, file_path);
|
||||
// bad_ble_script_set_default_keyboard_layout(bad_ble);
|
||||
|
||||
bad_ble->st.state = BadBleStateInit;
|
||||
bad_ble->st.error[0] = '\0';
|
||||
// bad_ble->st.state = BadBleStateInit;
|
||||
// bad_ble->st.error[0] = '\0';
|
||||
|
||||
bad_ble->bt = bt;
|
||||
// bad_ble->bt = bt;
|
||||
|
||||
bad_ble->thread = furi_thread_alloc_ex("BadBleWorker", 2048, bad_ble_worker, bad_ble);
|
||||
furi_thread_start(bad_ble->thread);
|
||||
return bad_ble;
|
||||
} //-V773
|
||||
// bad_ble->thread = furi_thread_alloc_ex("BadBleWorker", 2048, bad_ble_worker, bad_ble);
|
||||
// furi_thread_start(bad_ble->thread);
|
||||
// return bad_ble;
|
||||
// } //-V773
|
||||
|
||||
void bad_ble_script_close(BadBleScript* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtEnd);
|
||||
furi_thread_join(bad_ble->thread);
|
||||
furi_thread_free(bad_ble->thread);
|
||||
furi_string_free(bad_ble->file_path);
|
||||
free(bad_ble);
|
||||
}
|
||||
// void bad_ble_script_close(BadBleScript* bad_ble) {
|
||||
// furi_assert(bad_ble);
|
||||
// furi_record_close(RECORD_STORAGE);
|
||||
// furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtEnd);
|
||||
// furi_thread_join(bad_ble->thread);
|
||||
// furi_thread_free(bad_ble->thread);
|
||||
// furi_string_free(bad_ble->file_path);
|
||||
// free(bad_ble);
|
||||
// }
|
||||
|
||||
void bad_ble_script_set_keyboard_layout(BadBleScript* bad_ble, FuriString* layout_path) {
|
||||
furi_assert(bad_ble);
|
||||
// void bad_ble_script_set_keyboard_layout(BadBleScript* bad_ble, FuriString* layout_path) {
|
||||
// furi_assert(bad_ble);
|
||||
|
||||
if((bad_ble->st.state == BadBleStateRunning) || (bad_ble->st.state == BadBleStateDelay)) {
|
||||
// do not update keyboard layout while a script is running
|
||||
return;
|
||||
}
|
||||
// if((bad_ble->st.state == BadBleStateRunning) || (bad_ble->st.state == BadBleStateDelay)) {
|
||||
// // do not update keyboard layout while a script is running
|
||||
// return;
|
||||
// }
|
||||
|
||||
File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
if(!furi_string_empty(layout_path)) {
|
||||
if(storage_file_open(
|
||||
layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
uint16_t layout[128];
|
||||
if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) {
|
||||
memcpy(bad_ble->layout, layout, sizeof(layout));
|
||||
}
|
||||
}
|
||||
storage_file_close(layout_file);
|
||||
} else {
|
||||
bad_ble_script_set_default_keyboard_layout(bad_ble);
|
||||
}
|
||||
storage_file_free(layout_file);
|
||||
}
|
||||
// File* layout_file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
// if(!furi_string_empty(layout_path)) {
|
||||
// if(storage_file_open(
|
||||
// layout_file, furi_string_get_cstr(layout_path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
// uint16_t layout[128];
|
||||
// if(storage_file_read(layout_file, layout, sizeof(layout)) == sizeof(layout)) {
|
||||
// memcpy(bad_ble->layout, layout, sizeof(layout));
|
||||
// }
|
||||
// }
|
||||
// storage_file_close(layout_file);
|
||||
// } else {
|
||||
// bad_ble_script_set_default_keyboard_layout(bad_ble);
|
||||
// }
|
||||
// storage_file_free(layout_file);
|
||||
// }
|
||||
|
||||
void bad_ble_script_toggle(BadBleScript* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtToggle);
|
||||
}
|
||||
// void bad_ble_script_toggle(BadBleScript* bad_ble) {
|
||||
// furi_assert(bad_ble);
|
||||
// furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtToggle);
|
||||
// }
|
||||
|
||||
BadBleState* bad_ble_script_get_state(BadBleScript* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
return &(bad_ble->st);
|
||||
}
|
||||
// BadBleState* bad_ble_script_get_state(BadBleScript* bad_ble) {
|
||||
// furi_assert(bad_ble);
|
||||
// return &(bad_ble->st);
|
||||
// }
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <furi.h>
|
||||
#include <bt/bt_service/bt_i.h>
|
||||
|
||||
typedef struct BadBleScript BadBleScript;
|
||||
|
||||
typedef enum {
|
||||
BadBleStateInit,
|
||||
BadBleStateNotConnected,
|
||||
BadBleStateIdle,
|
||||
BadBleStateWillRun,
|
||||
BadBleStateRunning,
|
||||
BadBleStateDelay,
|
||||
BadBleStateDone,
|
||||
BadBleStateScriptError,
|
||||
BadBleStateFileError,
|
||||
} BadBleWorkerState;
|
||||
|
||||
typedef struct {
|
||||
BadBleWorkerState state;
|
||||
uint16_t line_cur;
|
||||
uint16_t line_nb;
|
||||
uint32_t delay_remain;
|
||||
uint16_t error_line;
|
||||
char error[64];
|
||||
} BadBleState;
|
||||
|
||||
BadBleScript* bad_ble_script_open(FuriString* file_path, Bt* bt);
|
||||
|
||||
void bad_ble_script_close(BadBleScript* bad_ble);
|
||||
|
||||
void bad_ble_script_set_keyboard_layout(BadBleScript* bad_ble, FuriString* layout_path);
|
||||
|
||||
void bad_ble_script_start(BadBleScript* bad_ble);
|
||||
|
||||
void bad_ble_script_stop(BadBleScript* bad_ble);
|
||||
|
||||
void bad_ble_script_toggle(BadBleScript* bad_ble);
|
||||
|
||||
BadBleState* bad_ble_script_get_state(BadBleScript* bad_ble);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define BAD_BLE_SETTINGS_FILE_NAME ".BadBle.settings"
|
||||
|
Before Width: | Height: | Size: 576 B |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 576 B |
|
Before Width: | Height: | Size: 147 B |
@@ -1,30 +0,0 @@
|
||||
#include "bad_ble_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const bad_ble_scene_on_enter_handlers[])(void*) = {
|
||||
#include "bad_ble_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const bad_ble_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "bad_ble_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const bad_ble_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "bad_ble_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers bad_ble_scene_handlers = {
|
||||
.on_enter_handlers = bad_ble_scene_on_enter_handlers,
|
||||
.on_event_handlers = bad_ble_scene_on_event_handlers,
|
||||
.on_exit_handlers = bad_ble_scene_on_exit_handlers,
|
||||
.scene_num = BadBleSceneNum,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) BadBleScene##id,
|
||||
typedef enum {
|
||||
#include "bad_ble_scene_config.h"
|
||||
BadBleSceneNum,
|
||||
} BadBleScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers bad_ble_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "bad_ble_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "bad_ble_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "bad_ble_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexKeyboardLayout,
|
||||
SubmenuIndexAdvertisementName,
|
||||
SubmenuIndexMacAddress,
|
||||
};
|
||||
|
||||
void bad_ble_scene_config_submenu_callback(void* context, uint32_t index) {
|
||||
BadBleApp* bad_ble = context;
|
||||
view_dispatcher_send_custom_event(bad_ble->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_on_enter(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
Submenu* submenu = bad_ble->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Keyboard layout",
|
||||
SubmenuIndexKeyboardLayout,
|
||||
bad_ble_scene_config_submenu_callback,
|
||||
bad_ble);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change adv name",
|
||||
SubmenuIndexAdvertisementName,
|
||||
bad_ble_scene_config_submenu_callback,
|
||||
bad_ble);
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Change MAC address",
|
||||
SubmenuIndexMacAddress,
|
||||
bad_ble_scene_config_submenu_callback,
|
||||
bad_ble);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(bad_ble->scene_manager, BadBleSceneConfig));
|
||||
|
||||
view_dispatcher_switch_to_view(bad_ble->view_dispatcher, BadBleAppViewConfig);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_config_on_event(void* context, SceneManagerEvent event) {
|
||||
BadBleApp* bad_ble = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(bad_ble->scene_manager, BadBleSceneConfig, event.event);
|
||||
consumed = true;
|
||||
if(event.event == SubmenuIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneConfigLayout);
|
||||
} else if(event.event == SubmenuIndexAdvertisementName) {
|
||||
scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneConfigName);
|
||||
} else if(event.event == SubmenuIndexMacAddress) {
|
||||
scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneConfigMac);
|
||||
} else {
|
||||
furi_crash("Unknown key type");
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_on_exit(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
Submenu* submenu = bad_ble->submenu;
|
||||
|
||||
submenu_reset(submenu);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
ADD_SCENE(bad_ble, file_select, FileSelect)
|
||||
ADD_SCENE(bad_ble, work, Work)
|
||||
ADD_SCENE(bad_ble, error, Error)
|
||||
ADD_SCENE(bad_ble, config, Config)
|
||||
ADD_SCENE(bad_ble, config_layout, ConfigLayout)
|
||||
ADD_SCENE(bad_ble, config_name, ConfigName)
|
||||
ADD_SCENE(bad_ble, config_mac, ConfigMac)
|
||||
@@ -1,47 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
static bool bad_ble_layout_select(BadBleApp* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
|
||||
FuriString* predefined_path;
|
||||
predefined_path = furi_string_alloc();
|
||||
if(!furi_string_empty(bad_ble->keyboard_layout)) {
|
||||
furi_string_set(predefined_path, bad_ble->keyboard_layout);
|
||||
} else {
|
||||
furi_string_set(predefined_path, BAD_BLE_APP_PATH_LAYOUT_FOLDER);
|
||||
}
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, BAD_BLE_APP_LAYOUT_EXTENSION, &I_keyboard_10px);
|
||||
|
||||
// Input events and views are managed by file_browser
|
||||
bool res = dialog_file_browser_show(
|
||||
bad_ble->dialogs, bad_ble->keyboard_layout, predefined_path, &browser_options);
|
||||
|
||||
furi_string_free(predefined_path);
|
||||
return res;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_layout_on_enter(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
if(bad_ble_layout_select(bad_ble)) {
|
||||
bad_ble_script_set_keyboard_layout(bad_ble->bad_ble_script, bad_ble->keyboard_layout);
|
||||
}
|
||||
scene_manager_previous_scene(bad_ble->scene_manager);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_config_layout_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
// BadBleApp* bad_ble = context;
|
||||
return false;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_layout_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
// BadBleApp* bad_ble = context;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
|
||||
#define TAG "BadBleConfigMac"
|
||||
|
||||
static uint8_t* reverse_mac_addr(uint8_t* mac) {
|
||||
uint8_t tmp;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
tmp = mac[i];
|
||||
mac[i] = mac[5 - i];
|
||||
mac[5 - i] = tmp;
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_mac_byte_input_callback(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
view_dispatcher_send_custom_event(bad_ble->view_dispatcher, BadBleAppCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_mac_on_enter(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = bad_ble->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter new MAC address");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
bad_ble_scene_config_mac_byte_input_callback,
|
||||
NULL,
|
||||
bad_ble,
|
||||
reverse_mac_addr(bad_ble->mac),
|
||||
GAP_MAC_ADDR_SIZE);
|
||||
view_dispatcher_switch_to_view(bad_ble->view_dispatcher, BadBleAppViewConfigMac);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_config_mac_on_event(void* context, SceneManagerEvent event) {
|
||||
BadBleApp* bad_ble = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == BadBleAppCustomEventByteInputDone) {
|
||||
bt_set_profile_mac_address(bad_ble->bt, reverse_mac_addr(bad_ble->mac));
|
||||
scene_manager_previous_scene(bad_ble->scene_manager);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_mac_on_exit(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(bad_ble->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(bad_ble->byte_input, "");
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
|
||||
static void bad_ble_scene_config_name_text_input_callback(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
bad_ble->view_dispatcher, BadBleAppCustomEventTextEditResult);
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_name_on_enter(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
TextInput* text_input = bad_ble->text_input;
|
||||
|
||||
text_input_set_header_text(text_input, "Set BLE adv name");
|
||||
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
bad_ble_scene_config_name_text_input_callback,
|
||||
bad_ble,
|
||||
bad_ble->name,
|
||||
BAD_BLE_ADV_NAME_MAX_LEN,
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(bad_ble->view_dispatcher, BadBleAppViewConfigName);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_config_name_on_event(void* context, SceneManagerEvent event) {
|
||||
BadBleApp* bad_ble = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == BadBleAppCustomEventTextEditResult) {
|
||||
bt_set_profile_adv_name(bad_ble->bt, bad_ble->name);
|
||||
}
|
||||
scene_manager_previous_scene(bad_ble->scene_manager);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_ble_scene_config_name_on_exit(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
TextInput* text_input = bad_ble->text_input;
|
||||
|
||||
text_input_reset(text_input);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
#include "../../../settings/desktop_settings/desktop_settings_app.h"
|
||||
|
||||
static void
|
||||
bad_ble_scene_error_event_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
BadBleApp* app = context;
|
||||
|
||||
if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, BadBleCustomEventErrorBack);
|
||||
}
|
||||
}
|
||||
|
||||
void bad_ble_scene_error_on_enter(void* context) {
|
||||
BadBleApp* app = context;
|
||||
DesktopSettings* settings = malloc(sizeof(DesktopSettings));
|
||||
DESKTOP_SETTINGS_LOAD(settings);
|
||||
|
||||
if(app->error == BadBleAppErrorNoFiles) {
|
||||
widget_add_icon_element(app->widget, 0, 0, &I_SDQuestion_35x43);
|
||||
widget_add_string_multiline_element(
|
||||
app->widget,
|
||||
81,
|
||||
4,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"No SD card or\napp data found.\nThis app will not\nwork without\nrequired files.");
|
||||
widget_add_button_element(
|
||||
app->widget, GuiButtonTypeLeft, "Back", bad_ble_scene_error_event_callback, app);
|
||||
} else if(app->error == BadBleAppErrorCloseRpc) {
|
||||
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!");
|
||||
widget_add_string_multiline_element(
|
||||
app->widget,
|
||||
3,
|
||||
30,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Disconnect from\nPC or phone to\nuse this function.");
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BadBleAppViewError);
|
||||
free(settings);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_error_on_event(void* context, SceneManagerEvent event) {
|
||||
BadBleApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == BadBleCustomEventErrorBack) {
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_ble_scene_error_on_exit(void* context) {
|
||||
BadBleApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#include "../bad_ble_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
static bool bad_ble_file_select(BadBleApp* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(
|
||||
&browser_options, BAD_BLE_APP_SCRIPT_EXTENSION, &I_badusb_10px);
|
||||
browser_options.base_path = BAD_BLE_APP_BASE_FOLDER;
|
||||
browser_options.skip_assets = true;
|
||||
|
||||
// Input events and views are managed by file_browser
|
||||
bool res = dialog_file_browser_show(
|
||||
bad_ble->dialogs, bad_ble->file_path, bad_ble->file_path, &browser_options);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void bad_ble_scene_file_select_on_enter(void* context) {
|
||||
BadBleApp* bad_ble = context;
|
||||
|
||||
// furi_hal_ble_disable();
|
||||
if(bad_ble->bad_ble_script) {
|
||||
bad_ble_script_close(bad_ble->bad_ble_script);
|
||||
bad_ble->bad_ble_script = NULL;
|
||||
}
|
||||
|
||||
if(bad_ble_file_select(bad_ble)) {
|
||||
bad_ble->bad_ble_script = bad_ble_script_open(bad_ble->file_path, bad_ble->bt);
|
||||
bad_ble_script_set_keyboard_layout(bad_ble->bad_ble_script, bad_ble->keyboard_layout);
|
||||
|
||||
scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneWork);
|
||||
} else {
|
||||
// furi_hal_ble_enable();
|
||||
view_dispatcher_stop(bad_ble->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
bool bad_ble_scene_file_select_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
// BadBleApp* bad_ble = context;
|
||||
return false;
|
||||
}
|
||||
|
||||
void bad_ble_scene_file_select_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
// BadBleApp* bad_ble = context;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "../bad_ble_script.h"
|
||||
#include "../bad_ble_app_i.h"
|
||||
#include "../views/bad_ble_view.h"
|
||||
#include "furi_hal.h"
|
||||
#include "toolbox/path.h"
|
||||
|
||||
void bad_ble_scene_work_button_callback(InputKey key, void* context) {
|
||||
furi_assert(context);
|
||||
BadBleApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, key);
|
||||
}
|
||||
|
||||
bool bad_ble_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
BadBleApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InputKeyLeft) {
|
||||
scene_manager_next_scene(app->scene_manager, BadBleSceneConfig);
|
||||
consumed = true;
|
||||
} else if(event.event == InputKeyOk) {
|
||||
bad_ble_script_toggle(app->bad_ble_script);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
bad_ble_set_state(app->bad_ble_view, bad_ble_script_get_state(app->bad_ble_script));
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_ble_scene_work_on_enter(void* context) {
|
||||
BadBleApp* app = context;
|
||||
|
||||
FuriString* file_name;
|
||||
file_name = furi_string_alloc();
|
||||
path_extract_filename(app->file_path, file_name, true);
|
||||
bad_ble_set_file_name(app->bad_ble_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_ble_set_layout(app->bad_ble_view, furi_string_get_cstr(layout));
|
||||
furi_string_free(layout);
|
||||
|
||||
bad_ble_set_state(app->bad_ble_view, bad_ble_script_get_state(app->bad_ble_script));
|
||||
|
||||
bad_ble_set_button_callback(app->bad_ble_view, bad_ble_scene_work_button_callback, app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BadBleAppViewWork);
|
||||
}
|
||||
|
||||
void bad_ble_scene_work_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
def analyze_and_replace(directory):
|
||||
# Recursively search for .c and .h files in the given directory
|
||||
for root, dirs, files in os.walk(directory):
|
||||
for file in files:
|
||||
if file.endswith(".c") or file.endswith(".h"):
|
||||
# Read the contents of the file
|
||||
with open(os.path.join(root, file), "r") as f:
|
||||
contents = f.read()
|
||||
|
||||
# Replace all occurrences of "BadUsb" and "bad_usb" with "BadBle" and "bad_ble"
|
||||
contents = contents.replace("usb", "ble")
|
||||
contents = contents.replace("USB", "BLE")
|
||||
contents = contents.replace("Usb", "Ble")
|
||||
|
||||
|
||||
# Write the modified contents back to the file
|
||||
with open(os.path.join(root, file), "w") as f:
|
||||
f.write(contents)
|
||||
|
||||
# Test the function with a sample directory
|
||||
analyze_and_replace(".")
|
||||
@@ -1,221 +0,0 @@
|
||||
#include "bad_ble_view.h"
|
||||
#include "../bad_ble_script.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <gui/elements.h>
|
||||
#include <bad_ble_icons.h>
|
||||
#include "../../../settings/desktop_settings/desktop_settings_app.h"
|
||||
|
||||
#define MAX_NAME_LEN 64
|
||||
|
||||
struct BadBle {
|
||||
View* view;
|
||||
BadBleButtonCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char file_name[MAX_NAME_LEN];
|
||||
char layout[MAX_NAME_LEN];
|
||||
BadBleState state;
|
||||
uint8_t anim_frame;
|
||||
} BadBleModel;
|
||||
|
||||
static void bad_ble_draw_callback(Canvas* canvas, void* _model) {
|
||||
BadBleModel* model = _model;
|
||||
|
||||
FuriString* disp_str;
|
||||
disp_str = furi_string_alloc_set(model->file_name);
|
||||
elements_string_fit_width(canvas, disp_str, 128 - 2);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 2, 8, furi_string_get_cstr(disp_str));
|
||||
DesktopSettings* settings = malloc(sizeof(DesktopSettings));
|
||||
DESKTOP_SETTINGS_LOAD(settings);
|
||||
|
||||
if(strlen(model->layout) == 0) {
|
||||
furi_string_set(disp_str, "(default)");
|
||||
} else {
|
||||
furi_string_reset(disp_str);
|
||||
furi_string_push_back(disp_str, '(');
|
||||
for(size_t i = 0; i < strlen(model->layout); i++)
|
||||
furi_string_push_back(disp_str, model->layout[i]);
|
||||
furi_string_push_back(disp_str, ')');
|
||||
}
|
||||
elements_string_fit_width(canvas, disp_str, 128 - 2);
|
||||
canvas_draw_str(
|
||||
canvas, 2, 8 + canvas_current_font_height(canvas), furi_string_get_cstr(disp_str));
|
||||
|
||||
furi_string_reset(disp_str);
|
||||
|
||||
canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22);
|
||||
|
||||
if((model->state.state == BadBleStateIdle) || (model->state.state == BadBleStateDone) ||
|
||||
(model->state.state == BadBleStateNotConnected)) {
|
||||
elements_button_center(canvas, "Start");
|
||||
} else if((model->state.state == BadBleStateRunning) || (model->state.state == BadBleStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadBleStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
||||
if((model->state.state == BadBleStateNotConnected) ||
|
||||
(model->state.state == BadBleStateIdle) || (model->state.state == BadBleStateDone)) {
|
||||
elements_button_left(canvas, "Config");
|
||||
}
|
||||
|
||||
if(model->state.state == BadBleStateNotConnected) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Connect me");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to a computer");
|
||||
} else if(model->state.state == BadBleStateWillRun) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "Will run");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "on connect");
|
||||
} else if(model->state.state == BadBleStateFileError) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 31, AlignRight, AlignBottom, "File");
|
||||
canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "ERROR");
|
||||
} else if(model->state.state == BadBleStateScriptError) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Error_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 127, 33, AlignRight, AlignBottom, "ERROR:");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
furi_string_printf(disp_str, "line %u", model->state.error_line);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_str_aligned(canvas, 127, 56, AlignRight, AlignBottom, model->state.error);
|
||||
} else if(model->state.state == BadBleStateIdle) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Smile_18x18);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "0");
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadBleStateRunning) {
|
||||
if(model->anim_frame == 0) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviSmile2_18x21);
|
||||
}
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
furi_string_printf(
|
||||
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadBleStateDone) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviSmile1_18x21);
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
canvas_draw_str_aligned(canvas, 114, 40, AlignRight, AlignBottom, "100");
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
} else if(model->state.state == BadBleStateDelay) {
|
||||
if(model->anim_frame == 0) {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting1_18x21);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 4, 23, &I_EviWaiting2_18x21);
|
||||
}
|
||||
canvas_set_font(canvas, FontBigNumbers);
|
||||
furi_string_printf(
|
||||
disp_str, "%u", ((model->state.line_cur - 1) * 100) / model->state.line_nb);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 114, 40, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
canvas_draw_icon(canvas, 117, 26, &I_Percent_10x14);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
furi_string_printf(disp_str, "delay %lus", model->state.delay_remain);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 127, 50, AlignRight, AlignBottom, furi_string_get_cstr(disp_str));
|
||||
furi_string_reset(disp_str);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
}
|
||||
|
||||
furi_string_free(disp_str);
|
||||
free(settings);
|
||||
}
|
||||
|
||||
static bool bad_ble_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
BadBle* bad_ble = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if((event->key == InputKeyLeft) || (event->key == InputKeyOk)) {
|
||||
consumed = true;
|
||||
furi_assert(bad_ble->callback);
|
||||
bad_ble->callback(event->key, bad_ble->context);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
BadBle* bad_ble_alloc() {
|
||||
BadBle* bad_ble = malloc(sizeof(BadBle));
|
||||
|
||||
bad_ble->view = view_alloc();
|
||||
view_allocate_model(bad_ble->view, ViewModelTypeLocking, sizeof(BadBleModel));
|
||||
view_set_context(bad_ble->view, bad_ble);
|
||||
view_set_draw_callback(bad_ble->view, bad_ble_draw_callback);
|
||||
view_set_input_callback(bad_ble->view, bad_ble_input_callback);
|
||||
|
||||
return bad_ble;
|
||||
}
|
||||
|
||||
void bad_ble_free(BadBle* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
view_free(bad_ble->view);
|
||||
free(bad_ble);
|
||||
}
|
||||
|
||||
View* bad_ble_get_view(BadBle* bad_ble) {
|
||||
furi_assert(bad_ble);
|
||||
return bad_ble->view;
|
||||
}
|
||||
|
||||
void bad_ble_set_button_callback(BadBle* bad_ble, BadBleButtonCallback callback, void* context) {
|
||||
furi_assert(bad_ble);
|
||||
furi_assert(callback);
|
||||
with_view_model(
|
||||
bad_ble->view,
|
||||
BadBleModel * model,
|
||||
{
|
||||
UNUSED(model);
|
||||
bad_ble->callback = callback;
|
||||
bad_ble->context = context;
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void bad_ble_set_file_name(BadBle* bad_ble, const char* name) {
|
||||
furi_assert(name);
|
||||
with_view_model(
|
||||
bad_ble->view,
|
||||
BadBleModel * model,
|
||||
{ strlcpy(model->file_name, name, MAX_NAME_LEN); },
|
||||
true);
|
||||
}
|
||||
|
||||
void bad_ble_set_layout(BadBle* bad_ble, const char* layout) {
|
||||
furi_assert(layout);
|
||||
with_view_model(
|
||||
bad_ble->view,
|
||||
BadBleModel * model,
|
||||
{ strlcpy(model->layout, layout, MAX_NAME_LEN); },
|
||||
true);
|
||||
}
|
||||
|
||||
void bad_ble_set_state(BadBle* bad_ble, BadBleState* st) {
|
||||
furi_assert(st);
|
||||
with_view_model(
|
||||
bad_ble->view,
|
||||
BadBleModel * model,
|
||||
{
|
||||
memcpy(&(model->state), st, sizeof(BadBleState));
|
||||
model->anim_frame ^= 1;
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
#include "../bad_ble_script.h"
|
||||
|
||||
typedef struct BadBle BadBle;
|
||||
typedef void (*BadBleButtonCallback)(InputKey key, void* context);
|
||||
|
||||
BadBle* bad_ble_alloc();
|
||||
|
||||
void bad_ble_free(BadBle* bad_ble);
|
||||
|
||||
View* bad_ble_get_view(BadBle* bad_ble);
|
||||
|
||||
void bad_ble_set_button_callback(BadBle* bad_ble, BadBleButtonCallback callback, void* context);
|
||||
|
||||
void bad_ble_set_file_name(BadBle* bad_ble, const char* name);
|
||||
|
||||
void bad_ble_set_layout(BadBle* bad_ble, const char* layout);
|
||||
|
||||
void bad_ble_set_state(BadBle* bad_ble, BadBleState* st);
|
||||
@@ -5,6 +5,9 @@
|
||||
#include <storage/storage.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
#include <bt/bt_service/bt_i.h>
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/" BAD_USB_SETTINGS_FILE_NAME
|
||||
|
||||
static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) {
|
||||
@@ -51,6 +54,17 @@ static void bad_usb_save_settings(BadUsbApp* app) {
|
||||
storage_file_free(settings_file);
|
||||
}
|
||||
|
||||
void bad_usb_set_name(BadUsbApp* app, const char* fmt, ...) {
|
||||
furi_assert(app);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(app->name, BAD_USB_ADV_NAME_MAX_LEN, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
BadUsbApp* bad_usb_app_alloc(char* arg) {
|
||||
BadUsbApp* app = malloc(sizeof(BadUsbApp));
|
||||
|
||||
@@ -81,19 +95,38 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, bad_usb_app_back_event_callback);
|
||||
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
app->bt = bt;
|
||||
const char* adv_name = bt_get_profile_adv_name(bt);
|
||||
memcpy(app->name, adv_name, BAD_USB_ADV_NAME_MAX_LEN);
|
||||
|
||||
const uint8_t* mac_addr = bt_get_profile_mac_address(bt);
|
||||
memcpy(app->mac, mac_addr, BAD_USB_MAC_ADDRESS_LEN);
|
||||
|
||||
// Custom Widget
|
||||
app->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget));
|
||||
|
||||
app->submenu = submenu_alloc();
|
||||
app->var_item_list_bt = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewConfig, submenu_get_view(app->submenu));
|
||||
app->view_dispatcher, BadUsbAppViewConfigBt, variable_item_list_get_view(app->var_item_list_bt));
|
||||
app->var_item_list_usb = variable_item_list_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewConfigUsb, variable_item_list_get_view(app->var_item_list_usb));
|
||||
|
||||
app->bad_usb_view = bad_usb_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewWork, bad_usb_get_view(app->bad_usb_view));
|
||||
|
||||
app->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewConfigName, text_input_get_view(app->text_input));
|
||||
|
||||
app->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BadUsbAppViewConfigMac, byte_input_get_view(app->byte_input));
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
if(furi_hal_usb_is_locked()) {
|
||||
@@ -101,7 +134,7 @@ BadUsbApp* bad_usb_app_alloc(char* arg) {
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneError);
|
||||
} else {
|
||||
if(!furi_string_empty(app->file_path)) {
|
||||
app->bad_usb_script = bad_usb_script_open(app->file_path);
|
||||
app->bad_usb_script = bad_usb_script_open(app->file_path, bt);
|
||||
bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout);
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneWork);
|
||||
} else {
|
||||
@@ -129,9 +162,19 @@ void bad_usb_app_free(BadUsbApp* app) {
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError);
|
||||
widget_free(app->widget);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig);
|
||||
submenu_free(app->submenu);
|
||||
// Variable item list
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigBt);
|
||||
variable_item_list_free(app->var_item_list_bt);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigUsb);
|
||||
variable_item_list_free(app->var_item_list_usb);
|
||||
|
||||
// Text Input
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigName);
|
||||
text_input_free(app->text_input);
|
||||
|
||||
// Byte Input
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfigMac);
|
||||
byte_input_free(app->byte_input);
|
||||
|
||||
// View dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
@@ -141,6 +184,7 @@ void bad_usb_app_free(BadUsbApp* app) {
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
furi_record_close(RECORD_BT);
|
||||
|
||||
bad_usb_save_settings(app);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ extern "C" {
|
||||
|
||||
typedef struct BadUsbApp BadUsbApp;
|
||||
|
||||
void bad_usb_set_name(BadUsbApp* app, const char* fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
#include <assets_icons.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include "views/bad_usb_view.h"
|
||||
|
||||
#define BAD_USB_APP_BASE_FOLDER ANY_PATH("badusb")
|
||||
@@ -20,11 +21,20 @@
|
||||
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
|
||||
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
|
||||
|
||||
#define BAD_USB_MAC_ADDRESS_LEN 6 // need replace with MAC size maccro
|
||||
#define BAD_USB_ADV_NAME_MAX_LEN 18
|
||||
|
||||
typedef enum {
|
||||
BadUsbAppErrorNoFiles,
|
||||
BadUsbAppErrorCloseRpc,
|
||||
} BadUsbAppError;
|
||||
|
||||
typedef enum BadUsbCustomEvent {
|
||||
BadUsbAppCustomEventTextEditResult,
|
||||
BadUsbAppCustomEventByteInputDone,
|
||||
BadUsbCustomEventErrorBack
|
||||
} BadUsbCustomEvent;
|
||||
|
||||
struct BadUsbApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
@@ -32,17 +42,29 @@ struct BadUsbApp {
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
Widget* widget;
|
||||
Submenu* submenu;
|
||||
VariableItemList* var_item_list_bt;
|
||||
VariableItemList* var_item_list_usb;
|
||||
|
||||
Bt* bt;
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
uint8_t mac[BAD_USB_MAC_ADDRESS_LEN];
|
||||
char name[BAD_USB_ADV_NAME_MAX_LEN + 1];
|
||||
|
||||
BadUsbAppError error;
|
||||
FuriString* file_path;
|
||||
FuriString* keyboard_layout;
|
||||
BadUsb* bad_usb_view;
|
||||
BadUsbScript* bad_usb_script;
|
||||
|
||||
bool is_bluetooth;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BadUsbAppViewError,
|
||||
BadUsbAppViewWork,
|
||||
BadUsbAppViewConfig,
|
||||
} BadUsbAppView;
|
||||
BadUsbAppViewConfigBt,
|
||||
BadUsbAppViewConfigUsb,
|
||||
BadUsbAppViewConfigMac,
|
||||
BadUsbAppViewConfigName
|
||||
} BadUsbAppView;
|
||||
|
||||
@@ -3,11 +3,16 @@
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
#include <lib/toolbox/args.h>
|
||||
#include <furi_hal_bt_hid.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <storage/storage.h>
|
||||
#include "bad_usb_script.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys")
|
||||
|
||||
#define TAG "BadUSB"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
#define FILE_BUFFER_LEN 16
|
||||
@@ -26,6 +31,27 @@ typedef enum {
|
||||
WorkerEvtDisconnect = (1 << 3),
|
||||
} WorkerEvtFlags;
|
||||
|
||||
typedef enum {
|
||||
LevelRssi122_100,
|
||||
LevelRssi99_80,
|
||||
LevelRssi79_60,
|
||||
LevelRssi59_40,
|
||||
LevelRssi39_0,
|
||||
LevelRssiNum,
|
||||
LevelRssiError = 0xFF,
|
||||
} LevelRssiRange;
|
||||
|
||||
/**
|
||||
* Delays for waiting between HID key press and key release
|
||||
*/
|
||||
const uint8_t bt_hid_delays[LevelRssiNum] = {
|
||||
30, // LevelRssi122_100
|
||||
25, // LevelRssi99_80
|
||||
20, // LevelRssi79_60
|
||||
17, // LevelRssi59_40
|
||||
14, // LevelRssi39_0
|
||||
};
|
||||
|
||||
struct BadUsbScript {
|
||||
FuriHalUsbHidConfig hid_cfg;
|
||||
BadUsbState st;
|
||||
@@ -41,6 +67,8 @@ struct BadUsbScript {
|
||||
|
||||
FuriString* line_prev;
|
||||
uint32_t repeat_cnt;
|
||||
|
||||
Bt* bt;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -75,8 +103,8 @@ static const DuckyKey ducky_keys[] = {
|
||||
{"BREAK", HID_KEYBOARD_PAUSE},
|
||||
{"PAUSE", HID_KEYBOARD_PAUSE},
|
||||
{"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
|
||||
{"DELETE", HID_KEYBOARD_DELETE_FORWARD},
|
||||
{"BACKSPACE", HID_KEYBOARD_DELETE},
|
||||
{"DELETE", HID_KEYBOARD_DELETE},
|
||||
{"BACKSPACE", HID_KEYPAD_BACKSPACE},
|
||||
{"END", HID_KEYBOARD_END},
|
||||
{"ESC", HID_KEYBOARD_ESCAPE},
|
||||
{"ESCAPE", HID_KEYBOARD_ESCAPE},
|
||||
@@ -134,6 +162,51 @@ static const uint8_t numpad_keys[10] = {
|
||||
HID_KEYPAD_9,
|
||||
};
|
||||
|
||||
uint8_t bt_timeout = 0;
|
||||
|
||||
static LevelRssiRange bt_remote_rssi_range(Bt* bt) {
|
||||
BtRssi rssi_data = {0};
|
||||
|
||||
if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError;
|
||||
|
||||
if(rssi_data.rssi <= 39)
|
||||
return LevelRssi39_0;
|
||||
else if(rssi_data.rssi <= 59)
|
||||
return LevelRssi59_40;
|
||||
else if(rssi_data.rssi <= 79)
|
||||
return LevelRssi79_60;
|
||||
else if(rssi_data.rssi <= 99)
|
||||
return LevelRssi99_80;
|
||||
else if(rssi_data.rssi <= 122)
|
||||
return LevelRssi122_100;
|
||||
|
||||
return LevelRssiError;
|
||||
}
|
||||
|
||||
static inline void update_bt_timeout(Bt* bt) {
|
||||
LevelRssiRange r = bt_remote_rssi_range(bt);
|
||||
if(r < LevelRssiNum) {
|
||||
bt_timeout = bt_hid_delays[r];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait until there are enough free slots in the keyboard buffer
|
||||
*
|
||||
* @param n_free_chars Number of free slots to wait for (and consider the buffer not full)
|
||||
*/
|
||||
// static void bt_hid_hold_while_keyboard_buffer_full(uint8_t n_free_chars, int32_t timeout) {
|
||||
// uint32_t start = furi_get_tick();
|
||||
// uint32_t timeout_ms = timeout <= -1 ? 0 : timeout;
|
||||
// while(furi_hal_bt_hid_kb_free_slots(n_free_chars) == false) {
|
||||
// furi_delay_ms(100);
|
||||
|
||||
// if(timeout != -1 && (furi_get_tick() - start) > timeout_ms) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
static bool ducky_get_number(const char* param, uint32_t* val) {
|
||||
uint32_t value = 0;
|
||||
if(sscanf(param, "%lu", &value) == 1) {
|
||||
@@ -664,7 +737,7 @@ static void bad_usb_script_set_default_keyboard_layout(BadUsbScript* bad_usb) {
|
||||
memcpy(bad_usb->layout, hid_asciimap, MIN(sizeof(hid_asciimap), sizeof(bad_usb->layout)));
|
||||
}
|
||||
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path, Bt* bt) {
|
||||
furi_assert(file_path);
|
||||
|
||||
BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
|
||||
@@ -675,6 +748,8 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
bad_usb->st.state = BadUsbStateInit;
|
||||
bad_usb->st.error[0] = '\0';
|
||||
|
||||
bad_usb->bt = bt;
|
||||
|
||||
bad_usb->thread = furi_thread_alloc_ex("BadUsbWorker", 2048, bad_usb_worker, bad_usb);
|
||||
furi_thread_start(bad_usb->thread);
|
||||
return bad_usb;
|
||||
@@ -682,6 +757,7 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path) {
|
||||
|
||||
void bad_usb_script_close(BadUsbScript* bad_usb) {
|
||||
furi_assert(bad_usb);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_usb->thread), WorkerEvtEnd);
|
||||
furi_thread_join(bad_usb->thread);
|
||||
furi_thread_free(bad_usb->thread);
|
||||
|
||||
@@ -5,6 +5,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <furi.h>
|
||||
#include <bt/bt_service/bt_i.h>
|
||||
|
||||
typedef struct BadUsbScript BadUsbScript;
|
||||
|
||||
@@ -29,7 +30,7 @@ typedef struct {
|
||||
char error[64];
|
||||
} BadUsbState;
|
||||
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path);
|
||||
BadUsbScript* bad_usb_script_open(FuriString* file_path, Bt* bt);
|
||||
|
||||
void bad_usb_script_close(BadUsbScript* bad_usb);
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
|
||||
enum SubmenuIndex {
|
||||
SubmenuIndexKeyboardLayout,
|
||||
};
|
||||
|
||||
void bad_usb_scene_config_submenu_callback(void* context, uint32_t index) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_on_enter(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
Submenu* submenu = bad_usb->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Keyboard layout",
|
||||
SubmenuIndexKeyboardLayout,
|
||||
bad_usb_scene_config_submenu_callback,
|
||||
bad_usb);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(bad_usb->scene_manager, BadUsbSceneConfig));
|
||||
|
||||
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfig);
|
||||
}
|
||||
|
||||
bool bad_usb_scene_config_on_event(void* context, SceneManagerEvent event) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfig, event.event);
|
||||
consumed = true;
|
||||
if(event.event == SubmenuIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout);
|
||||
} else {
|
||||
furi_crash("Unknown key type");
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_on_exit(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
Submenu* submenu = bad_usb->submenu;
|
||||
|
||||
submenu_reset(submenu);
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
ADD_SCENE(bad_usb, file_select, FileSelect)
|
||||
ADD_SCENE(bad_usb, work, Work)
|
||||
ADD_SCENE(bad_usb, error, Error)
|
||||
ADD_SCENE(bad_usb, config, Config)
|
||||
ADD_SCENE(bad_usb, config_bt, ConfigBt)
|
||||
ADD_SCENE(bad_usb, config_usb, ConfigUsb)
|
||||
ADD_SCENE(bad_usb, config_layout, ConfigLayout)
|
||||
ADD_SCENE(bad_usb, config_name, ConfigName)
|
||||
ADD_SCENE(bad_usb, config_mac, ConfigMac)
|
||||
|
||||
81
applications/main/bad_usb/scenes/bad_usb_scene_config_bt.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
|
||||
enum VarItemListIndex {
|
||||
VarItemListIndexConnection,
|
||||
VarItemListIndexKeyboardLayout,
|
||||
VarItemListIndexAdvertisementName,
|
||||
VarItemListIndexMacAddress,
|
||||
};
|
||||
|
||||
void bad_usb_scene_config_bt_connection_callback(VariableItem* item) {
|
||||
BadUsbApp* bad_usb = variable_item_get_context(item);
|
||||
bad_usb->is_bluetooth = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, bad_usb->is_bluetooth ? "BT" : "USB");
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, VarItemListIndexConnection);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_bt_var_item_list_callback(void* context, uint32_t index) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_bt_on_enter(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
VariableItemList* var_item_list = bad_usb->var_item_list_bt;
|
||||
VariableItem* item;
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Connection", 2, bad_usb_scene_config_bt_connection_callback, bad_usb);
|
||||
variable_item_set_current_value_index(item, bad_usb->is_bluetooth);
|
||||
variable_item_set_current_value_text(item, bad_usb->is_bluetooth ? "BT" : "USB");
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Keyboard layout", 0, NULL, bad_usb);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Change adv name", 0, NULL, bad_usb);
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Change MAC address", 0, NULL, bad_usb);
|
||||
|
||||
variable_item_list_set_enter_callback(var_item_list, bad_usb_scene_config_bt_var_item_list_callback, bad_usb);
|
||||
|
||||
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfigBt);
|
||||
}
|
||||
|
||||
bool bad_usb_scene_config_bt_on_event(void* context, SceneManagerEvent event) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfigBt, event.event);
|
||||
consumed = true;
|
||||
if(event.event == VarItemListIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout);
|
||||
} else if(event.event == VarItemListIndexConnection) {
|
||||
scene_manager_previous_scene(bad_usb->scene_manager);
|
||||
if (bad_usb->is_bluetooth) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigUsb);
|
||||
}
|
||||
} else if(event.event == VarItemListIndexAdvertisementName) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigName);
|
||||
} else if(event.event == VarItemListIndexMacAddress) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigMac);
|
||||
// } else {
|
||||
// furi_crash("Unknown key type");
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_bt_on_exit(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
VariableItemList* var_item_list = bad_usb->var_item_list_bt;
|
||||
|
||||
variable_item_list_reset(var_item_list);
|
||||
}
|
||||
57
applications/main/bad_usb/scenes/bad_usb_scene_config_mac.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
|
||||
#define TAG "BadUsbConfigMac"
|
||||
|
||||
static uint8_t* reverse_mac_addr(uint8_t* mac) {
|
||||
uint8_t tmp;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
tmp = mac[i];
|
||||
mac[i] = mac[5 - i];
|
||||
mac[5 - i] = tmp;
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_mac_byte_input_callback(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, BadUsbAppCustomEventByteInputDone);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_mac_on_enter(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
|
||||
// Setup view
|
||||
ByteInput* byte_input = bad_usb->byte_input;
|
||||
byte_input_set_header_text(byte_input, "Enter new MAC address");
|
||||
byte_input_set_result_callback(
|
||||
byte_input,
|
||||
bad_usb_scene_config_mac_byte_input_callback,
|
||||
NULL,
|
||||
bad_usb,
|
||||
reverse_mac_addr(bad_usb->mac),
|
||||
GAP_MAC_ADDR_SIZE);
|
||||
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfigMac);
|
||||
}
|
||||
|
||||
bool bad_usb_scene_config_mac_on_event(void* context, SceneManagerEvent event) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == BadUsbAppCustomEventByteInputDone) {
|
||||
bt_set_profile_mac_address(bad_usb->bt, reverse_mac_addr(bad_usb->mac));
|
||||
scene_manager_previous_scene(bad_usb->scene_manager);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_mac_on_exit(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
|
||||
// Clear view
|
||||
byte_input_set_result_callback(bad_usb->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(bad_usb->byte_input, "");
|
||||
}
|
||||
46
applications/main/bad_usb/scenes/bad_usb_scene_config_name.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
|
||||
static void bad_usb_scene_config_name_text_input_callback(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
bad_usb->view_dispatcher, BadUsbAppCustomEventTextEditResult);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_name_on_enter(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
TextInput* text_input = bad_usb->text_input;
|
||||
|
||||
text_input_set_header_text(text_input, "Set BLE adv name");
|
||||
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
bad_usb_scene_config_name_text_input_callback,
|
||||
bad_usb,
|
||||
bad_usb->name,
|
||||
BAD_USB_ADV_NAME_MAX_LEN,
|
||||
true);
|
||||
|
||||
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfigName);
|
||||
}
|
||||
|
||||
bool bad_usb_scene_config_name_on_event(void* context, SceneManagerEvent event) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == BadUsbAppCustomEventTextEditResult) {
|
||||
bt_set_profile_adv_name(bad_usb->bt, bad_usb->name);
|
||||
}
|
||||
scene_manager_previous_scene(bad_usb->scene_manager);
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_name_on_exit(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
TextInput* text_input = bad_usb->text_input;
|
||||
|
||||
text_input_reset(text_input);
|
||||
}
|
||||
69
applications/main/bad_usb/scenes/bad_usb_scene_config_usb.c
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_usb.h"
|
||||
|
||||
enum VarItemListIndex {
|
||||
VarItemListIndexConnection,
|
||||
VarItemListIndexKeyboardLayout,
|
||||
};
|
||||
|
||||
void bad_usb_scene_config_usb_connection_callback(VariableItem* item) {
|
||||
BadUsbApp* bad_usb = variable_item_get_context(item);
|
||||
bad_usb->is_bluetooth = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, bad_usb->is_bluetooth ? "BT" : "USB");
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, VarItemListIndexConnection);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_usb_var_item_list_callback(void* context, uint32_t index) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_usb_on_enter(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
VariableItemList* var_item_list = bad_usb->var_item_list_usb;
|
||||
VariableItem* item;
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Connection", 2, bad_usb_scene_config_usb_connection_callback, bad_usb);
|
||||
variable_item_set_current_value_index(item, bad_usb->is_bluetooth);
|
||||
variable_item_set_current_value_text(item, bad_usb->is_bluetooth ? "BT" : "USB");
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Keyboard layout", 0, NULL, bad_usb);
|
||||
|
||||
variable_item_list_set_enter_callback(var_item_list, bad_usb_scene_config_usb_var_item_list_callback, bad_usb);
|
||||
|
||||
view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewConfigUsb);
|
||||
}
|
||||
|
||||
bool bad_usb_scene_config_usb_on_event(void* context, SceneManagerEvent event) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
scene_manager_set_scene_state(bad_usb->scene_manager, BadUsbSceneConfigUsb, event.event);
|
||||
consumed = true;
|
||||
if(event.event == VarItemListIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout);
|
||||
} else if(event.event == VarItemListIndexConnection) {
|
||||
scene_manager_previous_scene(bad_usb->scene_manager);
|
||||
if (bad_usb->is_bluetooth) {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigUsb);
|
||||
}
|
||||
// } else {
|
||||
// furi_crash("Unknown key type");
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void bad_usb_scene_config_usb_on_exit(void* context) {
|
||||
BadUsbApp* bad_usb = context;
|
||||
VariableItemList* var_item_list = bad_usb->var_item_list_usb;
|
||||
|
||||
variable_item_list_reset(var_item_list);
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
#include "../bad_usb_app_i.h"
|
||||
#include "../../../settings/xtreme_settings/xtreme_settings.h"
|
||||
|
||||
typedef enum {
|
||||
BadUsbCustomEventErrorBack,
|
||||
} BadUsbCustomEvent;
|
||||
|
||||
static void
|
||||
bad_usb_scene_error_event_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -29,7 +29,7 @@ void bad_usb_scene_file_select_on_enter(void* context) {
|
||||
}
|
||||
|
||||
if(bad_usb_file_select(bad_usb)) {
|
||||
bad_usb->bad_usb_script = bad_usb_script_open(bad_usb->file_path);
|
||||
bad_usb->bad_usb_script = bad_usb_script_open(bad_usb->file_path, bad_usb->bt);
|
||||
bad_usb_script_set_keyboard_layout(bad_usb->bad_usb_script, bad_usb->keyboard_layout);
|
||||
|
||||
scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneWork);
|
||||
|
||||
@@ -16,7 +16,11 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InputKeyLeft) {
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneConfig);
|
||||
if (app->is_bluetooth) {
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, BadUsbSceneConfigUsb);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == InputKeyOk) {
|
||||
bad_usb_script_toggle(app->bad_usb_script);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,12.4,,
|
||||
Version,+,13.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@@ -1038,7 +1038,7 @@ Function,+,furi_hal_bt_serial_stop,void,
|
||||
Function,+,furi_hal_bt_serial_tx,_Bool,"uint8_t*, uint16_t"
|
||||
Function,+,furi_hal_bt_set_key_storage_change_callback,void,"BleGlueKeyStorageChangedCallback, void*"
|
||||
Function,+,furi_hal_bt_set_profile_adv_name,void,"FuriHalBtProfile, const char[( 1 + ( 8 + 1 ) ) - 1]"
|
||||
Function,+furi_hal_bt_set_profile_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]"
|
||||
Function,+,furi_hal_bt_set_profile_mac_addr,void,"FuriHalBtProfile, const uint8_t[( 6 )]"
|
||||
Function,+,furi_hal_bt_start_advertising,void,
|
||||
Function,+,furi_hal_bt_start_app,_Bool,"FuriHalBtProfile, GapEventCallback, void*"
|
||||
Function,+,furi_hal_bt_start_packet_rx,void,"uint8_t, uint8_t"
|
||||
@@ -4422,6 +4422,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
|
||||
|