mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
BadKB completely rework connection handling
Proper distinction between user and ID/BT_ID configs All init and deinit handled centrally in a cleaner way Moved USB HID config to be handled this way too Changing config doesn't reload the script file, less error/crash prone Remember MAC is now serial MAC +2, like bt remote has serial MAC +1
This commit is contained in:
@@ -89,41 +89,6 @@ static void bad_kb_save_settings(BadKbApp* app) {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
void bad_kb_reload_worker(BadKbApp* app) {
|
||||
bad_kb_script_close(app->bad_kb_script);
|
||||
app->bad_kb_script = bad_kb_script_open(app->file_path, app->is_bt ? app->bt : NULL, app);
|
||||
bad_kb_script_set_keyboard_layout(app->bad_kb_script, app->keyboard_layout);
|
||||
}
|
||||
|
||||
int32_t bad_kb_config_switch_mode(BadKbApp* app) {
|
||||
if(!app->is_bt) furi_hal_bt_stop_advertising();
|
||||
XTREME_SETTINGS()->bad_bt = app->is_bt;
|
||||
XTREME_SETTINGS_SAVE();
|
||||
bad_kb_reload_worker(app);
|
||||
if(app->is_bt) furi_hal_bt_start_advertising();
|
||||
bad_kb_config_refresh_menu(app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bad_kb_config_refresh_menu(BadKbApp* app) {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfig);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
|
||||
void bad_kb_config_switch_remember_mode(BadKbApp* app) {
|
||||
if(app->bt_remember) {
|
||||
furi_hal_bt_set_profile_pairing_method(
|
||||
FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo);
|
||||
bt_set_profile_mac_address(app->bt, (uint8_t*)&BAD_KB_BOUND_MAC_ADDRESS);
|
||||
bt_enable_peer_key_update(app->bt);
|
||||
} else {
|
||||
furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone);
|
||||
bt_set_profile_mac_address(app->bt, app->config.bt_mac);
|
||||
bt_disable_peer_key_update(app->bt);
|
||||
}
|
||||
bad_kb_reload_worker(app);
|
||||
}
|
||||
|
||||
BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
BadKbApp* app = malloc(sizeof(BadKbApp));
|
||||
|
||||
@@ -165,6 +130,8 @@ BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
app->bt->suppress_pin_screen = true;
|
||||
app->is_bt = XTREME_SETTINGS()->bad_bt;
|
||||
app->bt_remember = XTREME_SETTINGS()->bad_bt_remember;
|
||||
memcpy(BAD_KB_BOUND_MAC, furi_hal_version_get_ble_mac(), BAD_KB_MAC_LEN);
|
||||
BAD_KB_BOUND_MAC[2] += 2;
|
||||
|
||||
// Custom Widget
|
||||
app->widget = widget_alloc();
|
||||
@@ -193,7 +160,7 @@ BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
|
||||
app->conn_mode = BadKbConnModeNone;
|
||||
app->conn_init_thread =
|
||||
furi_thread_alloc_ex("BadKbConnInit", 1024, (FuriThreadCallback)bad_kb_conn_refresh, app);
|
||||
furi_thread_alloc_ex("BadKbConnInit", 1024, (FuriThreadCallback)bad_kb_conn_apply, app);
|
||||
furi_thread_start(app->conn_init_thread);
|
||||
if(!furi_string_empty(app->file_path)) {
|
||||
app->bad_kb_script = bad_kb_script_open(app->file_path, app->is_bt ? app->bt : NULL, app);
|
||||
@@ -247,6 +214,7 @@ void bad_kb_app_free(BadKbApp* app) {
|
||||
app->conn_init_thread = NULL;
|
||||
}
|
||||
bad_kb_conn_reset(app);
|
||||
if(app->hid_cfg) free(app->hid_cfg);
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
@@ -25,5 +25,3 @@ typedef enum {
|
||||
BadKbAppViewByteInput,
|
||||
BadKbAppViewTextInput
|
||||
} BadKbAppView;
|
||||
|
||||
void bad_kb_config_switch_remember_mode(BadKbApp* app);
|
||||
|
||||
@@ -11,9 +11,13 @@
|
||||
#include "ducky_script_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <toolbox/hex.h>
|
||||
#include <xtreme.h>
|
||||
#include "../scenes/bad_kb_scene.h"
|
||||
|
||||
const uint8_t BAD_KB_BOUND_MAC_ADDRESS[BAD_KB_MAC_LEN] = {0x41, 0x4a, 0xef, 0xb6, 0xa9, 0xd4};
|
||||
const uint8_t BAD_KB_EMPTY_MAC_ADDRESS[BAD_KB_MAC_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const uint8_t BAD_KB_EMPTY_MAC[BAD_KB_MAC_LEN] = FURI_HAL_BT_EMPTY_MAC_ADDR;
|
||||
|
||||
// Adjusts to serial MAC +2 in app init
|
||||
uint8_t BAD_KB_BOUND_MAC[BAD_KB_MAC_LEN] = FURI_HAL_BT_EMPTY_MAC_ADDR;
|
||||
|
||||
#define TAG "BadKB"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
@@ -305,51 +309,51 @@ static int32_t ducky_parse_line(BadKbScript* bad_kb, FuriString* line) {
|
||||
}
|
||||
|
||||
static bool ducky_set_usb_id(BadKbScript* bad_kb, const char* line) {
|
||||
if(sscanf(line, "%lX:%lX", &bad_kb->hid_cfg.vid, &bad_kb->hid_cfg.pid) == 2) {
|
||||
bad_kb->hid_cfg.manuf[0] = '\0';
|
||||
bad_kb->hid_cfg.product[0] = '\0';
|
||||
FuriHalUsbHidConfig* cfg = &bad_kb->app->id_config.usb_cfg;
|
||||
|
||||
if(sscanf(line, "%lX:%lX", &cfg->vid, &cfg->pid) == 2) {
|
||||
cfg->manuf[0] = '\0';
|
||||
cfg->product[0] = '\0';
|
||||
|
||||
uint8_t id_len = ducky_get_command_len(line);
|
||||
if(!ducky_is_line_end(line[id_len + 1])) {
|
||||
sscanf(
|
||||
&line[id_len + 1],
|
||||
"%31[^\r\n:]:%31[^\r\n]",
|
||||
bad_kb->hid_cfg.manuf,
|
||||
bad_kb->hid_cfg.product);
|
||||
sscanf(&line[id_len + 1], "%31[^\r\n:]:%31[^\r\n]", cfg->manuf, cfg->product);
|
||||
}
|
||||
FURI_LOG_D(
|
||||
WORKER_TAG,
|
||||
"set id: %04lX:%04lX mfr:%s product:%s",
|
||||
bad_kb->hid_cfg.vid,
|
||||
bad_kb->hid_cfg.pid,
|
||||
bad_kb->hid_cfg.manuf,
|
||||
bad_kb->hid_cfg.product);
|
||||
"set usb id: %04lX:%04lX mfr:%s product:%s",
|
||||
cfg->vid,
|
||||
cfg->pid,
|
||||
cfg->manuf,
|
||||
cfg->product);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ducky_set_bt_id(BadKbScript* bad_kb, const char* line) {
|
||||
BadKbConfig* cfg = &bad_kb->app->id_config;
|
||||
|
||||
size_t line_len = strlen(line);
|
||||
size_t mac_len = BAD_KB_MAC_LEN * 3;
|
||||
size_t mac_len = BAD_KB_MAC_LEN * 3; // 2 text chars + separator per byte
|
||||
if(line_len < mac_len + 1) return false; // MAC + at least 1 char for name
|
||||
|
||||
uint8_t mac[BAD_KB_MAC_LEN];
|
||||
for(size_t i = 0; i < BAD_KB_MAC_LEN; i++) {
|
||||
char a = line[i * 3];
|
||||
char b = line[i * 3 + 1];
|
||||
if((a < 'A' && a > 'F') || (a < '0' && a > '9') || (b < 'A' && b > 'F') ||
|
||||
(b < '0' && b > '9') || !hex_char_to_uint8(a, b, &mac[i])) {
|
||||
(b < '0' && b > '9') || !hex_char_to_uint8(a, b, &cfg->bt_mac[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, line + mac_len);
|
||||
bt_set_profile_mac_address(bad_kb->bt, mac);
|
||||
strlcpy(cfg->bt_name, line + mac_len, BAD_KB_NAME_LEN);
|
||||
FURI_LOG_D(WORKER_TAG, "set bt id: %s", line);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ducky_script_preload(BadKbScript* bad_kb, File* script_file) {
|
||||
static void ducky_script_preload(BadKbScript* bad_kb, File* script_file) {
|
||||
BadKbApp* app = bad_kb->app;
|
||||
uint8_t ret = 0;
|
||||
uint32_t line_len = 0;
|
||||
|
||||
@@ -376,81 +380,23 @@ static bool ducky_script_preload(BadKbScript* bad_kb, File* script_file) {
|
||||
}
|
||||
} while(ret > 0);
|
||||
|
||||
const char* line_tmp = furi_string_get_cstr(bad_kb->line);
|
||||
if(bad_kb->app->switch_mode_thread) {
|
||||
furi_thread_join(bad_kb->app->switch_mode_thread);
|
||||
furi_thread_free(bad_kb->app->switch_mode_thread);
|
||||
bad_kb->app->switch_mode_thread = NULL;
|
||||
}
|
||||
// Looking for ID or BT_ID command at first line
|
||||
bad_kb->set_usb_id = false;
|
||||
bad_kb->set_bt_id = false;
|
||||
bad_kb->has_usb_id = strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0;
|
||||
bad_kb->has_bt_id = strncmp(line_tmp, ducky_cmd_bt_id, strlen(ducky_cmd_bt_id)) == 0;
|
||||
if(bad_kb->has_usb_id) {
|
||||
if(bad_kb->bt) {
|
||||
bad_kb->app->is_bt = false;
|
||||
bad_kb->app->switch_mode_thread = furi_thread_alloc_ex(
|
||||
"BadKbSwitchMode",
|
||||
1024,
|
||||
(FuriThreadCallback)bad_kb_config_switch_mode,
|
||||
bad_kb->app);
|
||||
furi_thread_start(bad_kb->app->switch_mode_thread);
|
||||
return false;
|
||||
}
|
||||
bad_kb->set_usb_id = ducky_set_usb_id(bad_kb, &line_tmp[strlen(ducky_cmd_id) + 1]);
|
||||
} else if(bad_kb->has_bt_id) {
|
||||
if(!bad_kb->bt) {
|
||||
bad_kb->app->is_bt = true;
|
||||
bad_kb->app->switch_mode_thread = furi_thread_alloc_ex(
|
||||
"BadKbSwitchMode",
|
||||
1024,
|
||||
(FuriThreadCallback)bad_kb_config_switch_mode,
|
||||
bad_kb->app);
|
||||
furi_thread_start(bad_kb->app->switch_mode_thread);
|
||||
return false;
|
||||
}
|
||||
if(!bad_kb->app->bt_remember) {
|
||||
bad_kb->set_bt_id = ducky_set_bt_id(bad_kb, &line_tmp[strlen(ducky_cmd_bt_id) + 1]);
|
||||
}
|
||||
}
|
||||
bad_kb_config_refresh_menu(bad_kb->app);
|
||||
const char* line_tmp = furi_string_get_cstr(bad_kb->line);
|
||||
app->set_usb_id = false;
|
||||
app->set_bt_id = false;
|
||||
app->has_usb_id = strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0;
|
||||
app->has_bt_id = strncmp(line_tmp, ducky_cmd_bt_id, strlen(ducky_cmd_bt_id)) == 0;
|
||||
|
||||
if(bad_kb->bt) {
|
||||
if(!bad_kb->set_bt_id) {
|
||||
const char* bt_name = bad_kb->app->config.bt_name;
|
||||
const uint8_t* bt_mac = bad_kb->app->bt_remember ?
|
||||
(uint8_t*)&BAD_KB_BOUND_MAC_ADDRESS :
|
||||
bad_kb->app->config.bt_mac;
|
||||
bool reset_name = strncmp(
|
||||
bt_name,
|
||||
furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_NAME_LEN);
|
||||
bool reset_mac = memcmp(
|
||||
bt_mac,
|
||||
furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_MAC_LEN);
|
||||
if(reset_name && reset_mac) {
|
||||
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, bt_name);
|
||||
} else if(reset_name) {
|
||||
bt_set_profile_adv_name(bad_kb->bt, bt_name);
|
||||
}
|
||||
if(reset_mac) {
|
||||
bt_set_profile_mac_address(bad_kb->bt, bt_mac);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(bad_kb->set_usb_id) {
|
||||
furi_check(furi_hal_usb_set_config(&usb_hid, &bad_kb->hid_cfg));
|
||||
} else {
|
||||
furi_check(furi_hal_usb_set_config(&usb_hid, NULL));
|
||||
}
|
||||
if(app->has_usb_id) {
|
||||
app->is_bt = false;
|
||||
app->set_usb_id = ducky_set_usb_id(bad_kb, &line_tmp[strlen(ducky_cmd_id) + 1]);
|
||||
} else if(app->has_bt_id) {
|
||||
app->is_bt = true;
|
||||
app->set_bt_id = ducky_set_bt_id(bad_kb, &line_tmp[strlen(ducky_cmd_bt_id) + 1]);
|
||||
}
|
||||
|
||||
storage_file_seek(script_file, 0, true);
|
||||
furi_string_reset(bad_kb->line);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32_t ducky_script_execute_next(BadKbScript* bad_kb, File* script_file) {
|
||||
@@ -562,64 +508,68 @@ static uint32_t bad_kb_flags_get(uint32_t flags_mask, uint32_t timeout) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
int32_t bad_kb_conn_refresh(BadKbApp* app) {
|
||||
bool bt = app->is_bt;
|
||||
int32_t bad_kb_conn_apply(BadKbApp* app) {
|
||||
if(app->is_bt) {
|
||||
// Shorthands so this bs is readable
|
||||
BadKbConfig* prev = &app->prev_config;
|
||||
BadKbConfig* cfg = app->set_bt_id ? &app->id_config : &app->config;
|
||||
FuriHalBtProfile kbd = FuriHalBtProfileHidKeyboard;
|
||||
|
||||
if(app->conn_mode != BadKbConnModeNone) bad_kb_conn_reset(app);
|
||||
// Save prev config
|
||||
strcpy(prev->bt_name, furi_hal_bt_get_profile_adv_name(kbd));
|
||||
memcpy(prev->bt_mac, furi_hal_bt_get_profile_mac_addr(kbd), BAD_KB_MAC_LEN);
|
||||
prev->bt_mode = furi_hal_bt_get_profile_pairing_method(kbd);
|
||||
|
||||
if(bt) {
|
||||
strcpy(
|
||||
app->prev_config.bt_name,
|
||||
furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard));
|
||||
memcpy(
|
||||
app->prev_config.bt_mac,
|
||||
furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_MAC_LEN);
|
||||
app->prev_config.bt_mode =
|
||||
furi_hal_bt_get_profile_pairing_method(FuriHalBtProfileHidKeyboard);
|
||||
// Setup new config
|
||||
bt_timeout = bt_hid_delays[LevelRssi39_0];
|
||||
bt_disconnect(app->bt);
|
||||
furi_delay_ms(200);
|
||||
bt_keys_storage_set_storage_path(app->bt, BAD_KB_KEYS_PATH);
|
||||
if(strcmp(app->config.bt_name, "") != 0) {
|
||||
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->config.bt_name);
|
||||
}
|
||||
furi_hal_bt_set_profile_adv_name(kbd, cfg->bt_name);
|
||||
if(app->bt_remember) {
|
||||
furi_hal_bt_set_profile_mac_addr(
|
||||
FuriHalBtProfileHidKeyboard, (uint8_t*)&BAD_KB_BOUND_MAC_ADDRESS);
|
||||
furi_hal_bt_set_profile_pairing_method(
|
||||
FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo);
|
||||
furi_hal_bt_set_profile_mac_addr(kbd, BAD_KB_BOUND_MAC);
|
||||
furi_hal_bt_set_profile_pairing_method(kbd, GapPairingPinCodeVerifyYesNo);
|
||||
} else {
|
||||
if(memcmp(app->config.bt_mac, (uint8_t*)&BAD_KB_EMPTY_MAC_ADDRESS, BAD_KB_MAC_LEN) !=
|
||||
0) {
|
||||
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->config.bt_mac);
|
||||
}
|
||||
furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone);
|
||||
furi_hal_bt_set_profile_mac_addr(kbd, cfg->bt_mac);
|
||||
furi_hal_bt_set_profile_pairing_method(kbd, GapPairingNone);
|
||||
}
|
||||
|
||||
// Set profile, restart BT, adjust defaults
|
||||
furi_check(bt_set_profile(app->bt, BtProfileHidKeyboard));
|
||||
|
||||
// What was empty is now adjusted by furi_hal_bt so save the new defaults
|
||||
if(strcmp(app->config.bt_name, "") == 0) {
|
||||
strcpy(
|
||||
app->config.bt_name,
|
||||
furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard));
|
||||
}
|
||||
if(memcmp(app->config.bt_mac, (uint8_t*)&BAD_KB_EMPTY_MAC_ADDRESS, BAD_KB_MAC_LEN) == 0) {
|
||||
memcpy(
|
||||
app->config.bt_mac,
|
||||
furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_MAC_LEN);
|
||||
strcpy(app->config.bt_name, furi_hal_bt_get_profile_adv_name(kbd));
|
||||
}
|
||||
|
||||
// Advertise even if BT is off in settings
|
||||
furi_hal_bt_start_advertising();
|
||||
|
||||
// Toggle key callback after since BT restart resets it
|
||||
if(app->bt_remember) {
|
||||
bt_enable_peer_key_update(app->bt);
|
||||
} else {
|
||||
bt_disable_peer_key_update(app->bt);
|
||||
}
|
||||
furi_hal_bt_start_advertising();
|
||||
|
||||
app->conn_mode = BadKbConnModeBt;
|
||||
|
||||
} else {
|
||||
// Save prev config (TODO: maybe also restore config context?)
|
||||
app->prev_config.usb_mode = furi_hal_usb_get_config();
|
||||
|
||||
// Unlock RPC connections
|
||||
furi_hal_usb_unlock();
|
||||
furi_check(furi_hal_usb_set_config(NULL, NULL));
|
||||
|
||||
// Context will apply with set_config only if pointer address is different, so we use a copy
|
||||
FuriHalUsbHidConfig* hid_cfg = malloc(sizeof(FuriHalUsbHidConfig));
|
||||
memcpy(
|
||||
hid_cfg,
|
||||
app->set_usb_id ? &app->id_config.usb_cfg : &app->config.usb_cfg,
|
||||
sizeof(FuriHalUsbHidConfig));
|
||||
furi_check(furi_hal_usb_set_config(&usb_hid, hid_cfg));
|
||||
if(app->hid_cfg) free(app->hid_cfg);
|
||||
app->hid_cfg = hid_cfg;
|
||||
|
||||
app->conn_mode = BadKbConnModeUsb;
|
||||
}
|
||||
@@ -630,6 +580,7 @@ int32_t bad_kb_conn_refresh(BadKbApp* app) {
|
||||
void bad_kb_conn_reset(BadKbApp* app) {
|
||||
if(app->conn_mode == BadKbConnModeBt) {
|
||||
bt_disconnect(app->bt);
|
||||
furi_delay_ms(200);
|
||||
bt_keys_storage_set_default_path(app->bt);
|
||||
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->prev_config.bt_name);
|
||||
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->prev_config.bt_mac);
|
||||
@@ -645,6 +596,101 @@ void bad_kb_conn_reset(BadKbApp* app) {
|
||||
app->conn_mode = BadKbConnModeNone;
|
||||
}
|
||||
|
||||
void bad_kb_config_refresh(BadKbApp* app) {
|
||||
bt_set_status_changed_callback(app->bt, NULL, NULL);
|
||||
furi_hal_hid_set_state_callback(NULL, NULL);
|
||||
if(app->bad_kb_script) {
|
||||
furi_thread_flags_set(furi_thread_get_id(app->bad_kb_script->thread), WorkerEvtDisconnect);
|
||||
}
|
||||
if(app->conn_init_thread) {
|
||||
furi_thread_join(app->conn_init_thread);
|
||||
}
|
||||
|
||||
bool apply = false;
|
||||
if(app->is_bt) {
|
||||
BadKbConfig* cfg = app->set_bt_id ? &app->id_config : &app->config;
|
||||
|
||||
// MAC is adjusted by furi_hal_bt, adjust here too so it matches after applying
|
||||
const uint8_t* normal_mac = furi_hal_version_get_ble_mac();
|
||||
uint8_t empty_mac[BAD_KB_MAC_LEN] = FURI_HAL_BT_EMPTY_MAC_ADDR;
|
||||
uint8_t default_mac[BAD_KB_MAC_LEN] = FURI_HAL_BT_DEFAULT_MAC_ADDR;
|
||||
if(memcmp(cfg->bt_mac, empty_mac, BAD_KB_MAC_LEN) == 0 ||
|
||||
memcmp(cfg->bt_mac, normal_mac, BAD_KB_MAC_LEN) == 0 ||
|
||||
memcmp(cfg->bt_mac, default_mac, BAD_KB_MAC_LEN) == 0) {
|
||||
memcpy(cfg->bt_mac, normal_mac, BAD_KB_MAC_LEN);
|
||||
cfg->bt_mac[2]++;
|
||||
}
|
||||
|
||||
if(app->conn_mode != BadKbConnModeBt) {
|
||||
apply = true;
|
||||
bad_kb_conn_reset(app);
|
||||
} else {
|
||||
apply = apply || strncmp(
|
||||
cfg->bt_name,
|
||||
furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_NAME_LEN);
|
||||
apply = apply || memcmp(
|
||||
app->bt_remember ? BAD_KB_BOUND_MAC : cfg->bt_mac,
|
||||
furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard),
|
||||
BAD_KB_MAC_LEN);
|
||||
}
|
||||
} else {
|
||||
FuriHalUsbHidConfig* cfg = app->set_usb_id ? &app->id_config.usb_cfg :
|
||||
&app->config.usb_cfg;
|
||||
|
||||
if(app->conn_mode != BadKbConnModeUsb) {
|
||||
apply = true;
|
||||
bad_kb_conn_reset(app);
|
||||
} else {
|
||||
void* ctx;
|
||||
if(furi_hal_usb_get_config() == &usb_hid &&
|
||||
(ctx = furi_hal_usb_get_config_context()) != NULL) {
|
||||
FuriHalUsbHidConfig* cur = ctx;
|
||||
apply = apply || cfg->vid != cur->vid;
|
||||
apply = apply || cfg->pid != cur->pid;
|
||||
apply = apply || strncmp(cfg->manuf, cur->manuf, sizeof(cur->manuf));
|
||||
apply = apply || strncmp(cfg->product, cur->product, sizeof(cur->product));
|
||||
} else {
|
||||
apply = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(apply) {
|
||||
bad_kb_conn_apply(app);
|
||||
}
|
||||
|
||||
if(app->bad_kb_script) {
|
||||
BadKbScript* script = app->bad_kb_script;
|
||||
script->st.is_bt = app->is_bt;
|
||||
script->bt = app->is_bt ? app->bt : NULL;
|
||||
bool connected;
|
||||
if(app->is_bt) {
|
||||
bt_set_status_changed_callback(app->bt, bad_kb_bt_hid_state_callback, script);
|
||||
connected = furi_hal_bt_is_connected();
|
||||
} else {
|
||||
furi_hal_hid_set_state_callback(bad_kb_usb_hid_state_callback, script);
|
||||
connected = furi_hal_hid_is_connected();
|
||||
}
|
||||
if(connected) {
|
||||
furi_thread_flags_set(furi_thread_get_id(script->thread), WorkerEvtConnect);
|
||||
}
|
||||
}
|
||||
|
||||
// Reload config page
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfig);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
|
||||
// Update settings
|
||||
XtremeSettings* xtreme_settings = XTREME_SETTINGS();
|
||||
if(xtreme_settings->bad_bt != app->is_bt ||
|
||||
xtreme_settings->bad_bt_remember != app->bt_remember) {
|
||||
xtreme_settings->bad_bt = app->is_bt;
|
||||
xtreme_settings->bad_bt_remember = app->bt_remember;
|
||||
XTREME_SETTINGS_SAVE();
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t bad_kb_worker(void* context) {
|
||||
BadKbScript* bad_kb = context;
|
||||
|
||||
@@ -658,20 +704,6 @@ static int32_t bad_kb_worker(void* context) {
|
||||
bad_kb->line_prev = furi_string_alloc();
|
||||
bad_kb->string_print = furi_string_alloc();
|
||||
|
||||
if(bad_kb->app->conn_init_thread) {
|
||||
furi_thread_join(bad_kb->app->conn_init_thread);
|
||||
furi_thread_free(bad_kb->app->conn_init_thread);
|
||||
bad_kb->app->conn_init_thread = NULL;
|
||||
}
|
||||
|
||||
if(bad_kb->bt) {
|
||||
if(bad_kb->app->conn_mode != BadKbConnModeBt) bad_kb_conn_refresh(bad_kb->app);
|
||||
bt_set_status_changed_callback(bad_kb->bt, bad_kb_bt_hid_state_callback, bad_kb);
|
||||
} else {
|
||||
if(bad_kb->app->conn_mode != BadKbConnModeUsb) bad_kb_conn_refresh(bad_kb->app);
|
||||
furi_hal_hid_set_state_callback(bad_kb_usb_hid_state_callback, bad_kb);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
if(worker_state == BadKbStateInit) { // State: initialization
|
||||
FURI_LOG_D(WORKER_TAG, "init start");
|
||||
@@ -680,20 +712,10 @@ static int32_t bad_kb_worker(void* context) {
|
||||
furi_string_get_cstr(bad_kb->file_path),
|
||||
FSAM_READ,
|
||||
FSOM_OPEN_EXISTING)) {
|
||||
if((ducky_script_preload(bad_kb, script_file)) && (bad_kb->st.line_nb > 0)) {
|
||||
if(bad_kb->bt) {
|
||||
if(furi_hal_bt_is_connected()) {
|
||||
worker_state = BadKbStateIdle; // Ready to run
|
||||
} else {
|
||||
worker_state = BadKbStateNotConnected; // Not connected
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_hid_is_connected()) {
|
||||
worker_state = BadKbStateIdle; // Ready to run
|
||||
} else {
|
||||
worker_state = BadKbStateNotConnected; // Not connected
|
||||
}
|
||||
}
|
||||
ducky_script_preload(bad_kb, script_file);
|
||||
if(bad_kb->st.line_nb > 0) {
|
||||
bad_kb_config_refresh(bad_kb->app);
|
||||
worker_state = BadKbStateNotConnected; // Refresh will set connected flag
|
||||
} else {
|
||||
worker_state = BadKbStateScriptError; // Script preload error
|
||||
}
|
||||
@@ -989,11 +1011,8 @@ static int32_t bad_kb_worker(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
if(bad_kb->bt) {
|
||||
bt_set_status_changed_callback(bad_kb->bt, NULL, NULL);
|
||||
} else {
|
||||
furi_hal_hid_set_state_callback(NULL, NULL);
|
||||
}
|
||||
bt_set_status_changed_callback(bad_kb->app->bt, NULL, NULL);
|
||||
furi_hal_hid_set_state_callback(NULL, NULL);
|
||||
|
||||
storage_file_close(script_file);
|
||||
storage_file_free(script_file);
|
||||
|
||||
@@ -61,7 +61,6 @@ struct BadKbState {
|
||||
typedef struct BadKbApp BadKbApp;
|
||||
|
||||
typedef struct {
|
||||
FuriHalUsbHidConfig hid_cfg;
|
||||
FuriThread* thread;
|
||||
BadKbState st;
|
||||
|
||||
@@ -84,11 +83,6 @@ typedef struct {
|
||||
FuriString* string_print;
|
||||
size_t string_print_pos;
|
||||
|
||||
bool set_usb_id;
|
||||
bool set_bt_id;
|
||||
bool has_usb_id;
|
||||
bool has_bt_id;
|
||||
|
||||
Bt* bt;
|
||||
BadKbApp* app;
|
||||
} BadKbScript;
|
||||
@@ -112,19 +106,19 @@ BadKbState* bad_kb_script_get_state(BadKbScript* bad_kb);
|
||||
#define BAD_KB_NAME_LEN FURI_HAL_BT_ADV_NAME_LENGTH
|
||||
#define BAD_KB_MAC_LEN GAP_MAC_ADDR_SIZE
|
||||
|
||||
// this is the MAC address used when we do not forget paired device (BOUND STATE)
|
||||
extern const uint8_t BAD_KB_BOUND_MAC_ADDRESS[BAD_KB_MAC_LEN];
|
||||
extern const uint8_t BAD_KB_EMPTY_MAC_ADDRESS[BAD_KB_MAC_LEN];
|
||||
extern const uint8_t BAD_KB_EMPTY_MAC[BAD_KB_MAC_LEN];
|
||||
extern uint8_t BAD_KB_BOUND_MAC[BAD_KB_MAC_LEN]; // For remember mode
|
||||
|
||||
typedef enum {
|
||||
BadKbAppErrorNoFiles,
|
||||
} BadKbAppError;
|
||||
|
||||
typedef struct {
|
||||
GapPairing bt_mode;
|
||||
char bt_name[BAD_KB_NAME_LEN];
|
||||
uint8_t bt_mac[BAD_KB_MAC_LEN];
|
||||
FuriHalUsbInterface* usb_mode;
|
||||
GapPairing bt_mode;
|
||||
FuriHalUsbHidConfig usb_cfg;
|
||||
} BadKbConfig;
|
||||
|
||||
typedef enum {
|
||||
@@ -155,22 +149,26 @@ struct BadKbApp {
|
||||
Bt* bt;
|
||||
bool is_bt;
|
||||
bool bt_remember;
|
||||
BadKbConfig config;
|
||||
BadKbConfig prev_config;
|
||||
BadKbConfig config; // User options (TODO: allow users to change usb cfg)
|
||||
BadKbConfig id_config; // ID and BT_ID values
|
||||
BadKbConfig prev_config; // State to restore at exit
|
||||
|
||||
bool set_usb_id;
|
||||
bool set_bt_id;
|
||||
bool has_usb_id;
|
||||
bool has_bt_id;
|
||||
|
||||
FuriHalUsbHidConfig* hid_cfg;
|
||||
BadKbConnMode conn_mode;
|
||||
FuriThread* conn_init_thread;
|
||||
FuriThread* switch_mode_thread;
|
||||
};
|
||||
|
||||
int32_t bad_kb_config_switch_mode(BadKbApp* app);
|
||||
|
||||
void bad_kb_config_refresh_menu(BadKbApp* app);
|
||||
|
||||
int32_t bad_kb_conn_refresh(BadKbApp* app);
|
||||
int32_t bad_kb_conn_apply(BadKbApp* app);
|
||||
|
||||
void bad_kb_conn_reset(BadKbApp* app);
|
||||
|
||||
void bad_kb_config_refresh(BadKbApp* app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -23,8 +23,6 @@ void bad_kb_scene_config_connection_callback(VariableItem* item) {
|
||||
void bad_kb_scene_config_bt_remember_callback(VariableItem* item) {
|
||||
BadKbApp* bad_kb = variable_item_get_context(item);
|
||||
bad_kb->bt_remember = variable_item_get_current_value_index(item);
|
||||
XTREME_SETTINGS()->bad_bt_remember = bad_kb->bt_remember;
|
||||
XTREME_SETTINGS_SAVE();
|
||||
variable_item_set_current_value_text(item, bad_kb->bt_remember ? "ON" : "OFF");
|
||||
view_dispatcher_send_custom_event(bad_kb->view_dispatcher, VarItemListIndexBtRemember);
|
||||
}
|
||||
@@ -45,9 +43,9 @@ void bad_kb_scene_config_on_enter(void* context) {
|
||||
var_item_list, "Connection", 2, bad_kb_scene_config_connection_callback, bad_kb);
|
||||
variable_item_set_current_value_index(item, bad_kb->is_bt);
|
||||
variable_item_set_current_value_text(item, bad_kb->is_bt ? "BT" : "USB");
|
||||
if(bad_kb->bad_kb_script->has_usb_id) {
|
||||
if(bad_kb->has_usb_id) {
|
||||
variable_item_set_locked(item, true, "Script has\nID cmd!\nLocked to\nUSB Mode!");
|
||||
} else if(bad_kb->bad_kb_script->has_bt_id) {
|
||||
} else if(bad_kb->has_bt_id) {
|
||||
variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nBT Mode!");
|
||||
}
|
||||
|
||||
@@ -58,21 +56,21 @@ void bad_kb_scene_config_on_enter(void* context) {
|
||||
variable_item_set_current_value_text(item, bad_kb->bt_remember ? "ON" : "OFF");
|
||||
|
||||
item = variable_item_list_add(var_item_list, "BT Device Name", 0, NULL, bad_kb);
|
||||
if(bad_kb->bad_kb_script->set_bt_id) {
|
||||
if(bad_kb->set_bt_id) {
|
||||
variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset Name!");
|
||||
}
|
||||
|
||||
item = variable_item_list_add(var_item_list, "BT MAC Address", 0, NULL, bad_kb);
|
||||
if(bad_kb->bt_remember) {
|
||||
variable_item_set_locked(item, true, "Remember\nmust be Off!");
|
||||
} else if(bad_kb->bad_kb_script->set_bt_id) {
|
||||
} else if(bad_kb->set_bt_id) {
|
||||
variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!");
|
||||
}
|
||||
|
||||
item = variable_item_list_add(var_item_list, "Randomize BT MAC", 0, NULL, bad_kb);
|
||||
if(bad_kb->bt_remember) {
|
||||
variable_item_set_locked(item, true, "Remember\nmust be Off!");
|
||||
} else if(bad_kb->bad_kb_script->set_bt_id) {
|
||||
} else if(bad_kb->set_bt_id) {
|
||||
variable_item_set_locked(item, true, "Script has\nBT_ID cmd!\nLocked to\nset MAC!");
|
||||
}
|
||||
}
|
||||
@@ -97,14 +95,6 @@ bool bad_kb_scene_config_on_event(void* context, SceneManagerEvent event) {
|
||||
case VarItemListIndexKeyboardLayout:
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigLayout);
|
||||
break;
|
||||
case VarItemListIndexConnection:
|
||||
bad_kb_config_switch_mode(bad_kb);
|
||||
break;
|
||||
case VarItemListIndexBtRemember:
|
||||
bad_kb_config_switch_remember_mode(bad_kb);
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfig);
|
||||
break;
|
||||
case VarItemListIndexBtDeviceName:
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigName);
|
||||
break;
|
||||
@@ -113,7 +103,11 @@ bool bad_kb_scene_config_on_event(void* context, SceneManagerEvent event) {
|
||||
break;
|
||||
case VarItemListIndexRandomizeBtMac:
|
||||
furi_hal_random_fill_buf(bad_kb->config.bt_mac, BAD_KB_MAC_LEN);
|
||||
bt_set_profile_mac_address(bad_kb->bt, bad_kb->config.bt_mac);
|
||||
/* fall through */
|
||||
case VarItemListIndexBtRemember:
|
||||
/* fall through */
|
||||
case VarItemListIndexConnection:
|
||||
bad_kb_config_refresh(bad_kb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -35,7 +35,7 @@ bool bad_kb_scene_config_mac_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
if(event.event == BadKbAppCustomEventByteInputDone) {
|
||||
memmove(bad_kb->config.bt_mac, bad_kb->bt_mac_buf, BAD_KB_MAC_LEN);
|
||||
bt_set_profile_mac_address(bad_kb->bt, bad_kb->config.bt_mac);
|
||||
bad_kb_config_refresh(bad_kb);
|
||||
}
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ bool bad_kb_scene_config_name_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
if(event.event == BadKbAppCustomEventTextInputDone) {
|
||||
strlcpy(bad_kb->config.bt_name, bad_kb->bt_name_buf, BAD_KB_NAME_LEN);
|
||||
bt_set_profile_adv_name(bad_kb->bt, bad_kb->config.bt_name);
|
||||
bad_kb_config_refresh(bad_kb);
|
||||
}
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user