mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-27 01:58:09 -07:00
BadKB fixes and BT improvements (#143)
This commit is contained in:
@@ -72,17 +72,6 @@ static void bad_kb_save_settings(BadKbApp* app) {
|
||||
storage_file_free(settings_file);
|
||||
}
|
||||
|
||||
void bad_kb_set_name(BadKbApp* app, const char* fmt, ...) {
|
||||
furi_assert(app);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(app->name, BAD_KB_ADV_NAME_MAX_LEN, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
BadKbApp* app = malloc(sizeof(BadKbApp));
|
||||
|
||||
@@ -113,14 +102,19 @@ BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, bad_kb_app_back_event_callback);
|
||||
|
||||
app->connection_init = false;
|
||||
|
||||
Bt* bt = furi_record_open(RECORD_BT);
|
||||
app->bt = bt;
|
||||
app->bt->suppress_pin_screen = true;
|
||||
app->is_bt = XTREME_SETTINGS()->bad_bt;
|
||||
const char* adv_name = bt_get_profile_adv_name(bt);
|
||||
app->bt_remember = XTREME_SETTINGS()->bad_bt_remember;
|
||||
const char* adv_name = furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard);
|
||||
memcpy(app->name, adv_name, BAD_KB_ADV_NAME_MAX_LEN);
|
||||
memcpy(app->bt_old_config.name, adv_name, BAD_KB_ADV_NAME_MAX_LEN);
|
||||
|
||||
const uint8_t* mac_addr = bt_get_profile_mac_address(bt);
|
||||
// need to be done before bt init (where mac address get modified if bounding is activated)
|
||||
const uint8_t* mac_addr = furi_hal_bt_get_profile_mac_addr(FuriHalBtProfileHidKeyboard);
|
||||
memcpy(app->mac, mac_addr, BAD_KB_MAC_ADDRESS_LEN);
|
||||
memcpy(app->bt_old_config.mac, mac_addr, BAD_KB_MAC_ADDRESS_LEN);
|
||||
|
||||
@@ -156,8 +150,12 @@ BadKbApp* bad_kb_app_alloc(char* arg) {
|
||||
|
||||
if(furi_hal_usb_is_locked()) {
|
||||
app->error = BadKbAppErrorCloseRpc;
|
||||
app->conn_init_thread = NULL;
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneError);
|
||||
} else {
|
||||
app->conn_init_thread = furi_thread_alloc_ex(
|
||||
"BadKbConnInit", 512, (FuriThreadCallback)bad_kb_connection_init, 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);
|
||||
bad_kb_script_set_keyboard_layout(app->bad_kb_script, app->keyboard_layout);
|
||||
@@ -205,16 +203,16 @@ void bad_kb_app_free(BadKbApp* app) {
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// restores bt config
|
||||
// BtProfile have already been switched to the previous one
|
||||
// so we directly modify the right profile
|
||||
bad_kb_connection_deinit(app->bt);
|
||||
// Restore bt config
|
||||
// BtProfile has already been switched to the previous one
|
||||
// So we directly modify the right profile
|
||||
if(strcmp(app->bt_old_config.name, app->name) != 0) {
|
||||
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, app->bt_old_config.name);
|
||||
}
|
||||
if(memcmp(app->bt_old_config.mac, app->mac, BAD_KB_MAC_ADDRESS_LEN) != 0) {
|
||||
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->bt_old_config.mac);
|
||||
}
|
||||
app->bt->suppress_pin_screen = false;
|
||||
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
@@ -227,6 +225,12 @@ void bad_kb_app_free(BadKbApp* app) {
|
||||
furi_string_free(app->file_path);
|
||||
furi_string_free(app->keyboard_layout);
|
||||
|
||||
if(app->conn_init_thread) {
|
||||
furi_thread_join(app->conn_init_thread);
|
||||
furi_thread_free(app->conn_init_thread);
|
||||
}
|
||||
bad_kb_connection_deinit(app);
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ extern "C" {
|
||||
|
||||
typedef struct BadKbApp BadKbApp;
|
||||
|
||||
void bad_kb_set_name(BadKbApp* app, const char* fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,12 +18,17 @@
|
||||
|
||||
#define BAD_KB_APP_BASE_FOLDER ANY_PATH("badkb")
|
||||
#define BAD_KB_APP_PATH_LAYOUT_FOLDER BAD_KB_APP_BASE_FOLDER "/assets/layouts"
|
||||
#define BAD_KB_APP_PATH_BOUND_KEYS_FOLDER EXT_PATH("badkb/.bt_keys")
|
||||
#define BAD_KB_APP_PATH_BOUND_KEYS_FILE BAD_KB_APP_PATH_BOUND_KEYS_FOLDER "/.devices.keys"
|
||||
#define BAD_KB_APP_SCRIPT_EXTENSION ".txt"
|
||||
#define BAD_KB_APP_LAYOUT_EXTENSION ".kl"
|
||||
|
||||
#define BAD_KB_MAC_ADDRESS_LEN 6 // need replace with MAC size maccro
|
||||
#define BAD_KB_ADV_NAME_MAX_LEN 18
|
||||
|
||||
// this is the MAC address used when we do not forget paired device (BOUND STATE)
|
||||
#define BAD_KB_BOUND_MAC_ADDRESS {0x41, 0x4a, 0xef, 0xb6, 0xa9, 0xd4};
|
||||
|
||||
typedef enum {
|
||||
BadKbAppErrorNoFiles,
|
||||
BadKbAppErrorCloseRpc,
|
||||
@@ -36,12 +41,9 @@ typedef enum BadKbCustomEvent {
|
||||
} BadKbCustomEvent;
|
||||
|
||||
typedef struct {
|
||||
//uint8_t bounded_mac[BAD_KB_MAC_ADDRESS_LEN];
|
||||
uint8_t mac[BAD_KB_MAC_ADDRESS_LEN];
|
||||
char name[BAD_KB_ADV_NAME_MAX_LEN + 1];
|
||||
|
||||
// number of bt keys before starting the app (all keys added in
|
||||
// the bt keys file then will be removed)
|
||||
uint16_t n_keys;
|
||||
} BadKbBtConfig;
|
||||
|
||||
struct BadKbApp {
|
||||
@@ -59,6 +61,7 @@ struct BadKbApp {
|
||||
ByteInput* byte_input;
|
||||
uint8_t mac[BAD_KB_MAC_ADDRESS_LEN];
|
||||
char name[BAD_KB_ADV_NAME_MAX_LEN + 1];
|
||||
bool bt_remember; // weither we remember paired devices or not
|
||||
BadKbBtConfig bt_old_config;
|
||||
|
||||
BadKbAppError error;
|
||||
@@ -68,6 +71,12 @@ struct BadKbApp {
|
||||
BadKbScript* bad_kb_script;
|
||||
|
||||
bool is_bt;
|
||||
|
||||
bool connection_init;
|
||||
FuriHalUsbInterface* usb_prev_mode;
|
||||
GapPairing bt_prev_mode;
|
||||
|
||||
FuriThread* conn_init_thread;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <bt/bt_service/bt.h>
|
||||
|
||||
#include "bad_kb_app_i.h"
|
||||
|
||||
#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys")
|
||||
|
||||
#define TAG "BadKB"
|
||||
@@ -41,12 +43,6 @@ typedef enum {
|
||||
LevelRssiError = 0xFF,
|
||||
} LevelRssiRange;
|
||||
|
||||
typedef enum {
|
||||
BadKbConnectionModeNone,
|
||||
BadKbConnectionModeUsb,
|
||||
BadKbConnectionModeBt,
|
||||
} BadKbConnectionMode;
|
||||
|
||||
/**
|
||||
* Delays for waiting between HID key press and key release
|
||||
*/
|
||||
@@ -65,6 +61,7 @@ struct BadKbScript {
|
||||
FuriString* keyboard_layout;
|
||||
uint32_t defdelay;
|
||||
uint16_t layout[128];
|
||||
uint32_t stringdelay;
|
||||
FuriThread* thread;
|
||||
uint8_t file_buf[FILE_BUFFER_LEN + 1];
|
||||
uint8_t buf_start;
|
||||
@@ -148,6 +145,8 @@ 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_stringdelay_1[] = {"STRINGDELAY "};
|
||||
static const char ducky_cmd_stringdelay_2[] = {"STRING_DELAY "};
|
||||
static const char ducky_cmd_repeat[] = {"REPEAT "};
|
||||
static const char ducky_cmd_sysrq[] = {"SYSRQ "};
|
||||
|
||||
@@ -170,27 +169,22 @@ static const uint8_t numpad_keys[10] = {
|
||||
HID_KEYPAD_9,
|
||||
};
|
||||
|
||||
BadKbConnectionMode connection_mode = BadKbConnectionModeNone;
|
||||
FuriHalUsbInterface* usb_mode_prev = NULL;
|
||||
GapPairing bt_mode_prev = GapPairingNone;
|
||||
bool bt_connected = false;
|
||||
bool usb_connected = false;
|
||||
uint8_t bt_timeout = 0;
|
||||
|
||||
static LevelRssiRange bt_remote_rssi_range(Bt* bt) {
|
||||
BtRssi rssi_data = {0};
|
||||
uint8_t rssi;
|
||||
|
||||
if(!bt_remote_rssi(bt, &rssi_data)) return LevelRssiError;
|
||||
if(!bt_remote_rssi(bt, &rssi)) return LevelRssiError;
|
||||
|
||||
if(rssi_data.rssi <= 39)
|
||||
if(rssi <= 39)
|
||||
return LevelRssi39_0;
|
||||
else if(rssi_data.rssi <= 59)
|
||||
else if(rssi <= 59)
|
||||
return LevelRssi59_40;
|
||||
else if(rssi_data.rssi <= 79)
|
||||
else if(rssi <= 79)
|
||||
return LevelRssi79_60;
|
||||
else if(rssi_data.rssi <= 99)
|
||||
else if(rssi <= 99)
|
||||
return LevelRssi99_80;
|
||||
else if(rssi_data.rssi <= 122)
|
||||
else if(rssi <= 122)
|
||||
return LevelRssi122_100;
|
||||
|
||||
return LevelRssiError;
|
||||
@@ -304,6 +298,7 @@ static bool ducky_altstring(BadKbScript* bad_kb, const char* param) {
|
||||
|
||||
static bool ducky_string(BadKbScript* bad_kb, const char* param) {
|
||||
uint32_t i = 0;
|
||||
|
||||
while(param[i] != '\0') {
|
||||
uint16_t keycode = BADKB_ASCII_TO_KEY(bad_kb, param[i]);
|
||||
if(keycode != HID_KEYBOARD_NONE) {
|
||||
@@ -315,9 +310,13 @@ static bool ducky_string(BadKbScript* bad_kb, const char* param) {
|
||||
furi_hal_hid_kb_press(keycode);
|
||||
furi_hal_hid_kb_release(keycode);
|
||||
}
|
||||
if(bad_kb->stringdelay > 0) {
|
||||
furi_delay_ms(bad_kb->stringdelay);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
bad_kb->stringdelay = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -379,6 +378,19 @@ static int32_t
|
||||
snprintf(error, error_len, "Invalid number %s", line_tmp);
|
||||
}
|
||||
return (state) ? (0) : SCRIPT_STATE_ERROR;
|
||||
} else if(
|
||||
(strncmp(line_tmp, ducky_cmd_stringdelay_1, strlen(ducky_cmd_stringdelay_1)) == 0) ||
|
||||
(strncmp(line_tmp, ducky_cmd_stringdelay_2, strlen(ducky_cmd_stringdelay_2)) == 0)) {
|
||||
//STRINGDELAY, finally it's here
|
||||
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
|
||||
state = ducky_get_number(line_tmp, &bad_kb->stringdelay);
|
||||
if((state) && (bad_kb->stringdelay > 0)) {
|
||||
return state;
|
||||
}
|
||||
if(error != NULL) {
|
||||
snprintf(error, error_len, "Invalid number %s", line_tmp);
|
||||
}
|
||||
return SCRIPT_STATE_ERROR;
|
||||
} else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
|
||||
// STRING
|
||||
line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1];
|
||||
@@ -607,10 +619,8 @@ static void bad_kb_bt_hid_state_callback(BtStatus status, void* context) {
|
||||
if(r != LevelRssiError) {
|
||||
bt_timeout = bt_hid_delays[r];
|
||||
}
|
||||
bt_connected = true;
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_kb->thread), WorkerEvtConnect);
|
||||
} else {
|
||||
bt_connected = false;
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_kb->thread), WorkerEvtDisconnect);
|
||||
}
|
||||
}
|
||||
@@ -620,83 +630,116 @@ static void bad_kb_usb_hid_state_callback(bool state, void* context) {
|
||||
BadKbScript* bad_kb = context;
|
||||
|
||||
if(state == true) {
|
||||
usb_connected = true;
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_kb->thread), WorkerEvtConnect);
|
||||
} else {
|
||||
usb_connected = false;
|
||||
furi_thread_flags_set(furi_thread_get_id(bad_kb->thread), WorkerEvtDisconnect);
|
||||
}
|
||||
}
|
||||
|
||||
void bad_kb_bt_init(Bt* bt) {
|
||||
bt_timeout = bt_hid_delays[LevelRssi39_0];
|
||||
bt_disconnect(bt);
|
||||
furi_delay_ms(200);
|
||||
bt_keys_storage_set_storage_path(bt, HID_BT_KEYS_STORAGE_PATH);
|
||||
furi_assert(bt_set_profile(bt, BtProfileHidKeyboard));
|
||||
bt_mode_prev = bt_get_profile_pairing_method(bt);
|
||||
bt_set_profile_pairing_method(bt, GapPairingNone);
|
||||
furi_hal_bt_start_advertising();
|
||||
// disable peer key adding to bt SRAM storage
|
||||
bt_disable_peer_key_update(bt);
|
||||
|
||||
connection_mode = BadKbConnectionModeBt;
|
||||
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);
|
||||
bad_kb_script_set_keyboard_layout(app->bad_kb_script, app->keyboard_layout);
|
||||
}
|
||||
|
||||
void bad_kb_bt_deinit(Bt* bt) {
|
||||
// release all keys
|
||||
// bt_hid_hold_while_keyboard_buffer_full(6, 3000);
|
||||
void bad_kb_config_switch_mode(BadKbApp* app) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
if(app->is_bt) {
|
||||
furi_hal_bt_start_advertising();
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigBt);
|
||||
} else {
|
||||
furi_hal_bt_stop_advertising();
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigUsb);
|
||||
}
|
||||
bad_kb_reload_worker(app);
|
||||
}
|
||||
|
||||
// stop ble
|
||||
bt_disconnect(bt);
|
||||
void bad_kb_config_switch_remember_mode(BadKbApp* app) {
|
||||
if(app->bt_remember) {
|
||||
// set bouding mac
|
||||
uint8_t mac[6] = BAD_KB_BOUND_MAC_ADDRESS;
|
||||
furi_hal_bt_set_profile_pairing_method(
|
||||
FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo);
|
||||
bt_set_profile_mac_address(app->bt, mac); // this also restart bt
|
||||
// enable keys storage
|
||||
bt_enable_peer_key_update(app->bt);
|
||||
} else {
|
||||
// set back user defined mac address
|
||||
furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone);
|
||||
bt_set_profile_mac_address(app->bt, app->mac);
|
||||
// disable key storage
|
||||
bt_disable_peer_key_update(app->bt);
|
||||
}
|
||||
bad_kb_reload_worker(app);
|
||||
}
|
||||
|
||||
// Wait 2nd core to update nvm storage
|
||||
furi_delay_ms(200);
|
||||
int32_t bad_kb_connection_init(BadKbApp* app) {
|
||||
app->usb_prev_mode = furi_hal_usb_get_config();
|
||||
furi_hal_usb_set_config(NULL, NULL);
|
||||
|
||||
bt_keys_storage_set_default_path(bt);
|
||||
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_APP_PATH_BOUND_KEYS_FILE);
|
||||
app->bt_prev_mode = furi_hal_bt_get_profile_pairing_method(FuriHalBtProfileHidKeyboard);
|
||||
if(app->bt_remember) {
|
||||
uint8_t mac[6] = BAD_KB_BOUND_MAC_ADDRESS;
|
||||
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, mac);
|
||||
// using GapPairingNone breaks bounding between devices
|
||||
furi_hal_bt_set_profile_pairing_method(
|
||||
FuriHalBtProfileHidKeyboard, GapPairingPinCodeVerifyYesNo);
|
||||
} else {
|
||||
furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, GapPairingNone);
|
||||
}
|
||||
|
||||
bt_set_profile_pairing_method(bt, bt_mode_prev);
|
||||
bt_set_profile(app->bt, BtProfileHidKeyboard);
|
||||
if(app->is_bt) {
|
||||
furi_hal_bt_start_advertising();
|
||||
if(app->bt_remember) {
|
||||
bt_enable_peer_key_update(app->bt);
|
||||
} else {
|
||||
bt_disable_peer_key_update(app->bt); // disable peer key adding to bt SRAM storage
|
||||
}
|
||||
} else {
|
||||
furi_hal_bt_stop_advertising();
|
||||
}
|
||||
|
||||
app->connection_init = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bad_kb_connection_deinit(BadKbApp* app) {
|
||||
if(!app->connection_init) return;
|
||||
|
||||
furi_hal_usb_set_config(app->usb_prev_mode, NULL);
|
||||
|
||||
// bt_hid_hold_while_keyboard_buffer_full(6, 3000); // release all keys
|
||||
bt_disconnect(app->bt); // stop ble
|
||||
// furi_delay_ms(200); // Wait 2nd core to update nvm storage
|
||||
bt_keys_storage_set_default_path(app->bt);
|
||||
if(app->bt_remember) {
|
||||
// hal primitives doesn't restarts ble, that's what we want cuz we are shutting down
|
||||
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, app->mac);
|
||||
}
|
||||
bt_enable_peer_key_update(app->bt); // starts saving peer keys (bounded devices)
|
||||
// fails if ble radio stack isn't ready when switching profile
|
||||
// if it happens, maybe we should increase the delay after bt_disconnect
|
||||
bt_set_profile(bt, BtProfileSerial);
|
||||
|
||||
// starts saving peer keys (bounded devices)
|
||||
bt_enable_peer_key_update(bt);
|
||||
|
||||
connection_mode = BadKbConnectionModeNone;
|
||||
bt_set_profile(app->bt, BtProfileSerial);
|
||||
furi_hal_bt_set_profile_pairing_method(FuriHalBtProfileHidKeyboard, app->bt_prev_mode);
|
||||
}
|
||||
|
||||
void bad_kb_usb_init() {
|
||||
usb_mode_prev = furi_hal_usb_get_config();
|
||||
|
||||
connection_mode = BadKbConnectionModeUsb;
|
||||
}
|
||||
|
||||
void bad_kb_usb_deinit() {
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
|
||||
connection_mode = BadKbConnectionModeNone;
|
||||
}
|
||||
|
||||
void bad_kb_connection_init(Bt* bt) {
|
||||
if(connection_mode != BadKbConnectionModeNone) return;
|
||||
|
||||
if(bt) {
|
||||
bad_kb_bt_init(bt);
|
||||
static uint32_t bad_kb_flags_get(uint32_t flags_mask, uint32_t timeout) {
|
||||
uint32_t flags = furi_thread_flags_get();
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags == 0) {
|
||||
flags = furi_thread_flags_wait(flags_mask, FuriFlagWaitAny, timeout);
|
||||
furi_check(((flags & FuriFlagError) == 0) || (flags == (unsigned)FuriFlagErrorTimeout));
|
||||
} else {
|
||||
bad_kb_usb_init();
|
||||
}
|
||||
}
|
||||
|
||||
void bad_kb_connection_deinit(Bt* bt) {
|
||||
if(connection_mode == BadKbConnectionModeNone) return;
|
||||
|
||||
if(connection_mode == BadKbConnectionModeBt) {
|
||||
bad_kb_bt_deinit(bt);
|
||||
} else {
|
||||
bad_kb_usb_deinit();
|
||||
uint32_t state = furi_thread_flags_clear(flags);
|
||||
furi_check((state & FuriFlagError) == 0);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int32_t bad_kb_worker(void* context) {
|
||||
@@ -705,8 +748,6 @@ static int32_t bad_kb_worker(void* context) {
|
||||
BadKbWorkerState worker_state = BadKbStateInit;
|
||||
int32_t delay_val = 0;
|
||||
|
||||
bad_kb_connection_init(bad_kb->bt);
|
||||
|
||||
if(bad_kb->bt) {
|
||||
bt_set_status_changed_callback(bad_kb->bt, bad_kb_bt_hid_state_callback, bad_kb);
|
||||
} else {
|
||||
@@ -727,7 +768,11 @@ static int32_t bad_kb_worker(void* context) {
|
||||
FSOM_OPEN_EXISTING)) {
|
||||
if((ducky_script_preload(bad_kb, script_file)) && (bad_kb->st.line_nb > 0)) {
|
||||
if(bad_kb->bt) {
|
||||
worker_state = BadKbStateNotConnected; // Ready to run
|
||||
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
|
||||
@@ -745,30 +790,20 @@ static int32_t bad_kb_worker(void* context) {
|
||||
bad_kb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadKbStateNotConnected) { // State: Not connected
|
||||
if((bad_kb->bt && bt_connected) || (!bad_kb->bt && usb_connected)) {
|
||||
uint32_t flags = bad_kb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) {
|
||||
worker_state = BadKbStateIdle; // Ready to run
|
||||
} else {
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) {
|
||||
worker_state = BadKbStateIdle; // Ready to run
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
worker_state = BadKbStateWillRun; // Will run when connected
|
||||
}
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
worker_state = BadKbStateWillRun; // Will run when connected
|
||||
}
|
||||
bad_kb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadKbStateIdle) { // State: ready to start
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
uint32_t flags = bad_kb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtToggle | WorkerEvtDisconnect, FuriWaitForever);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtToggle) { // Start executing script
|
||||
@@ -777,6 +812,7 @@ static int32_t bad_kb_worker(void* context) {
|
||||
bad_kb->buf_len = 0;
|
||||
bad_kb->st.line_cur = 0;
|
||||
bad_kb->defdelay = 0;
|
||||
bad_kb->stringdelay = 0;
|
||||
bad_kb->repeat_cnt = 0;
|
||||
bad_kb->file_end = false;
|
||||
storage_file_seek(script_file, 0, true);
|
||||
@@ -788,11 +824,8 @@ static int32_t bad_kb_worker(void* context) {
|
||||
bad_kb->st.state = worker_state;
|
||||
|
||||
} else if(worker_state == BadKbStateWillRun) { // State: start on connection
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny,
|
||||
FuriWaitForever);
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
uint32_t flags = bad_kb_flags_get(
|
||||
WorkerEvtEnd | WorkerEvtConnect | WorkerEvtToggle, FuriWaitForever);
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
} else if(flags & WorkerEvtConnect) { // Start executing script
|
||||
@@ -801,16 +834,26 @@ static int32_t bad_kb_worker(void* context) {
|
||||
bad_kb->buf_len = 0;
|
||||
bad_kb->st.line_cur = 0;
|
||||
bad_kb->defdelay = 0;
|
||||
bad_kb->stringdelay = 0;
|
||||
bad_kb->repeat_cnt = 0;
|
||||
bad_kb->file_end = false;
|
||||
storage_file_seek(script_file, 0, true);
|
||||
// extra time for PC to recognize Flipper as keyboard
|
||||
furi_thread_flags_wait(0, FuriFlagWaitAny, 1500);
|
||||
flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtToggle,
|
||||
FuriFlagWaitAny | FuriFlagNoClear,
|
||||
1500);
|
||||
if(flags == (unsigned)FuriFlagErrorTimeout) {
|
||||
// If nothing happened - start script execution
|
||||
worker_state = BadKbStateRunning;
|
||||
} else if(flags & WorkerEvtToggle) {
|
||||
worker_state = BadKbStateIdle;
|
||||
furi_thread_flags_clear(WorkerEvtToggle);
|
||||
}
|
||||
if(bad_kb->bt) {
|
||||
update_bt_timeout(bad_kb->bt);
|
||||
}
|
||||
bad_kb_script_set_keyboard_layout(bad_kb, bad_kb->keyboard_layout);
|
||||
worker_state = BadKbStateRunning;
|
||||
} else if(flags & WorkerEvtToggle) { // Cancel scheduled execution
|
||||
worker_state = BadKbStateNotConnected;
|
||||
}
|
||||
@@ -875,9 +918,8 @@ static int32_t bad_kb_worker(void* context) {
|
||||
} else if(
|
||||
(worker_state == BadKbStateFileError) ||
|
||||
(worker_state == BadKbStateScriptError)) { // State: error
|
||||
uint32_t flags = furi_thread_flags_wait(
|
||||
WorkerEvtEnd, FuriFlagWaitAny, FuriWaitForever); // Waiting for exit command
|
||||
furi_check((flags & FuriFlagError) == 0);
|
||||
uint32_t flags =
|
||||
bad_kb_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command
|
||||
if(flags & WorkerEvtEnd) {
|
||||
break;
|
||||
}
|
||||
@@ -921,6 +963,7 @@ BadKbScript* bad_kb_script_open(FuriString* file_path, Bt* bt) {
|
||||
|
||||
bad_kb->st.state = BadKbStateInit;
|
||||
bad_kb->st.error[0] = '\0';
|
||||
bad_kb->st.is_bt = !!bt;
|
||||
|
||||
bad_kb->bt = bt;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ extern "C" {
|
||||
#include <furi.h>
|
||||
#include <bt/bt_service/bt_i.h>
|
||||
|
||||
typedef struct BadKbApp BadKbApp;
|
||||
|
||||
typedef struct BadKbScript BadKbScript;
|
||||
|
||||
typedef enum {
|
||||
@@ -23,6 +25,8 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
BadKbWorkerState state;
|
||||
bool is_bt;
|
||||
uint32_t pin;
|
||||
uint16_t line_cur;
|
||||
uint16_t line_nb;
|
||||
uint32_t delay_remain;
|
||||
@@ -30,9 +34,13 @@ typedef struct {
|
||||
char error[64];
|
||||
} BadKbState;
|
||||
|
||||
void bad_kb_connection_init(Bt* bt);
|
||||
void bad_kb_config_switch_mode(BadKbApp* app);
|
||||
|
||||
void bad_kb_connection_deinit(Bt* bt);
|
||||
void bad_kb_config_switch_remember_mode(BadKbApp* app);
|
||||
|
||||
int32_t bad_kb_connection_init(BadKbApp* app);
|
||||
|
||||
void bad_kb_connection_deinit(BadKbApp* app);
|
||||
|
||||
BadKbScript* bad_kb_script_open(FuriString* file_path, Bt* bt);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
enum VarItemListIndex {
|
||||
VarItemListIndexConnection,
|
||||
VarItemListIndexRemember,
|
||||
VarItemListIndexKeyboardLayout,
|
||||
VarItemListIndexAdvertisementName,
|
||||
VarItemListIndexMacAddress,
|
||||
@@ -19,6 +20,15 @@ void bad_kb_scene_config_bt_connection_callback(VariableItem* item) {
|
||||
view_dispatcher_send_custom_event(bad_kb->view_dispatcher, VarItemListIndexConnection);
|
||||
}
|
||||
|
||||
void bad_kb_scene_config_bt_bounding_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, VarItemListIndexRemember);
|
||||
}
|
||||
|
||||
void bad_kb_scene_config_bt_var_item_list_callback(void* context, uint32_t index) {
|
||||
BadKbApp* bad_kb = context;
|
||||
view_dispatcher_send_custom_event(bad_kb->view_dispatcher, index);
|
||||
@@ -34,11 +44,19 @@ void bad_kb_scene_config_bt_on_enter(void* context) {
|
||||
variable_item_set_current_value_index(item, bad_kb->is_bt);
|
||||
variable_item_set_current_value_text(item, bad_kb->is_bt ? "BT" : "USB");
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "Remember", 2, bad_kb_scene_config_bt_bounding_callback, bad_kb);
|
||||
variable_item_set_current_value_index(item, bad_kb->bt_remember);
|
||||
variable_item_set_current_value_text(item, bad_kb->bt_remember ? "ON" : "OFF");
|
||||
|
||||
item = variable_item_list_add(var_item_list, "Keyboard layout", 0, NULL, bad_kb);
|
||||
|
||||
item = variable_item_list_add(var_item_list, "BT device name", 0, NULL, bad_kb);
|
||||
|
||||
item = variable_item_list_add(var_item_list, "BT MAC address", 0, NULL, bad_kb);
|
||||
// this doesn't update instantly when toggling between Bounding modes
|
||||
if(!bad_kb->bt_remember) {
|
||||
item = variable_item_list_add(var_item_list, "BT MAC address", 0, NULL, bad_kb);
|
||||
}
|
||||
|
||||
variable_item_list_set_enter_callback(
|
||||
var_item_list, bad_kb_scene_config_bt_var_item_list_callback, bad_kb);
|
||||
@@ -56,23 +74,15 @@ bool bad_kb_scene_config_bt_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == VarItemListIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigLayout);
|
||||
} else if(event.event == VarItemListIndexConnection) {
|
||||
bad_kb_script_close(bad_kb->bad_kb_script);
|
||||
bad_kb_connection_deinit(bad_kb->bt);
|
||||
bad_kb->bad_kb_script =
|
||||
bad_kb_script_open(bad_kb->file_path, bad_kb->is_bt ? bad_kb->bt : NULL);
|
||||
bad_kb_script_set_keyboard_layout(bad_kb->bad_kb_script, bad_kb->keyboard_layout);
|
||||
bad_kb_config_switch_mode(bad_kb);
|
||||
} else if(event.event == VarItemListIndexRemember) {
|
||||
bad_kb_config_switch_remember_mode(bad_kb);
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
if(bad_kb->is_bt) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigUsb);
|
||||
}
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigBt);
|
||||
} else if(event.event == VarItemListIndexAdvertisementName) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigName);
|
||||
} else if(event.event == VarItemListIndexMacAddress) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigMac);
|
||||
// } else {
|
||||
// furi_crash("Unknown key type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
#define TAG "BadKbConfigMac"
|
||||
|
||||
static uint8_t* reverse_mac_addr(uint8_t* mac) {
|
||||
static uint8_t* reverse_mac_addr(uint8_t* mac, uint8_t* out) {
|
||||
uint8_t tmp;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
tmp = mac[i];
|
||||
mac[i] = mac[5 - i];
|
||||
mac[5 - i] = tmp;
|
||||
out[i] = mac[5 - i];
|
||||
out[5 - i] = tmp;
|
||||
}
|
||||
return mac;
|
||||
return out;
|
||||
}
|
||||
|
||||
void bad_kb_scene_config_mac_byte_input_callback(void* context) {
|
||||
@@ -29,7 +29,7 @@ void bad_kb_scene_config_mac_on_enter(void* context) {
|
||||
bad_kb_scene_config_mac_byte_input_callback,
|
||||
NULL,
|
||||
bad_kb,
|
||||
reverse_mac_addr(bad_kb->mac),
|
||||
reverse_mac_addr(bad_kb->mac, bad_kb->mac),
|
||||
GAP_MAC_ADDR_SIZE);
|
||||
view_dispatcher_switch_to_view(bad_kb->view_dispatcher, BadKbAppViewConfigMac);
|
||||
}
|
||||
@@ -40,7 +40,8 @@ bool bad_kb_scene_config_mac_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == BadKbAppCustomEventByteInputDone) {
|
||||
bt_set_profile_mac_address(bad_kb->bt, reverse_mac_addr(bad_kb->mac));
|
||||
uint8_t mac[GAP_MAC_ADDR_SIZE];
|
||||
bt_set_profile_mac_address(bad_kb->bt, reverse_mac_addr(bad_kb->mac, mac));
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
consumed = true;
|
||||
}
|
||||
@@ -54,4 +55,7 @@ void bad_kb_scene_config_mac_on_exit(void* context) {
|
||||
// Clear view
|
||||
byte_input_set_result_callback(bad_kb->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||
byte_input_set_header_text(bad_kb->byte_input, "");
|
||||
|
||||
// reverse back addr (in case it didn't get modified)
|
||||
reverse_mac_addr(bad_kb->mac, bad_kb->mac);
|
||||
}
|
||||
|
||||
@@ -50,19 +50,7 @@ bool bad_kb_scene_config_usb_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == VarItemListIndexKeyboardLayout) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigLayout);
|
||||
} else if(event.event == VarItemListIndexConnection) {
|
||||
bad_kb_script_close(bad_kb->bad_kb_script);
|
||||
bad_kb_connection_deinit(bad_kb->bt);
|
||||
bad_kb->bad_kb_script =
|
||||
bad_kb_script_open(bad_kb->file_path, bad_kb->is_bt ? bad_kb->bt : NULL);
|
||||
bad_kb_script_set_keyboard_layout(bad_kb->bad_kb_script, bad_kb->keyboard_layout);
|
||||
scene_manager_previous_scene(bad_kb->scene_manager);
|
||||
if(bad_kb->is_bt) {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneConfigUsb);
|
||||
}
|
||||
// } else {
|
||||
// furi_crash("Unknown key type");
|
||||
bad_kb_config_switch_mode(bad_kb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ static bool bad_kb_file_select(BadKbApp* bad_kb) {
|
||||
void bad_kb_scene_file_select_on_enter(void* context) {
|
||||
BadKbApp* bad_kb = context;
|
||||
|
||||
furi_hal_usb_disable();
|
||||
if(bad_kb->bad_kb_script) {
|
||||
bad_kb_script_close(bad_kb->bad_kb_script);
|
||||
bad_kb->bad_kb_script = NULL;
|
||||
@@ -35,7 +34,6 @@ void bad_kb_scene_file_select_on_enter(void* context) {
|
||||
|
||||
scene_manager_next_scene(bad_kb->scene_manager, BadKbSceneWork);
|
||||
} else {
|
||||
furi_hal_usb_enable();
|
||||
view_dispatcher_stop(bad_kb->view_dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@ bool bad_kb_scene_work_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == InputKeyLeft) {
|
||||
if(app->is_bt) {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigUsb);
|
||||
if(bad_kb_is_idle_state(app->bad_kb_view)) {
|
||||
if(app->is_bt) {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigBt);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, BadKbSceneConfigUsb);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == InputKeyOk) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "bad_kb_view.h"
|
||||
#include "../bad_kb_script.h"
|
||||
#include "../bad_kb_app_i.h"
|
||||
#include <toolbox/path.h>
|
||||
#include <gui/elements.h>
|
||||
#include <assets_icons.h>
|
||||
@@ -24,7 +25,8 @@ static void bad_kb_draw_callback(Canvas* canvas, void* _model) {
|
||||
BadKbModel* model = _model;
|
||||
|
||||
FuriString* disp_str;
|
||||
disp_str = furi_string_alloc_set(model->file_name);
|
||||
disp_str = furi_string_alloc_set(model->state.is_bt ? "(BT) " : "(USB) ");
|
||||
furi_string_cat_str(disp_str, 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));
|
||||
@@ -38,6 +40,9 @@ static void bad_kb_draw_callback(Canvas* canvas, void* _model) {
|
||||
furi_string_push_back(disp_str, model->layout[i]);
|
||||
furi_string_push_back(disp_str, ')');
|
||||
}
|
||||
if(model->state.pin) {
|
||||
furi_string_cat_printf(disp_str, " PIN: %ld", model->state.pin);
|
||||
}
|
||||
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));
|
||||
@@ -51,19 +56,15 @@ static void bad_kb_draw_callback(Canvas* canvas, void* _model) {
|
||||
if(XTREME_ASSETS()->is_nsfw) {
|
||||
elements_button_center(canvas, "Cum");
|
||||
} else {
|
||||
elements_button_center(canvas, "Start");
|
||||
elements_button_center(canvas, "Run");
|
||||
}
|
||||
elements_button_left(canvas, "Config");
|
||||
} else if((model->state.state == BadKbStateRunning) || (model->state.state == BadKbStateDelay)) {
|
||||
elements_button_center(canvas, "Stop");
|
||||
} else if(model->state.state == BadKbStateWillRun) {
|
||||
elements_button_center(canvas, "Cancel");
|
||||
}
|
||||
|
||||
if((model->state.state == BadKbStateNotConnected) || (model->state.state == BadKbStateIdle) ||
|
||||
(model->state.state == BadKbStateDone)) {
|
||||
elements_button_left(canvas, "Config");
|
||||
}
|
||||
|
||||
if(model->state.state == BadKbStateNotConnected) {
|
||||
canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
@@ -214,6 +215,14 @@ void bad_kb_set_layout(BadKb* bad_kb, const char* layout) {
|
||||
|
||||
void bad_kb_set_state(BadKb* bad_kb, BadKbState* st) {
|
||||
furi_assert(st);
|
||||
uint32_t pin = 0;
|
||||
if(bad_kb->context != NULL) {
|
||||
BadKbApp* app = bad_kb->context;
|
||||
if(app->bt != NULL) {
|
||||
pin = app->bt->pin;
|
||||
}
|
||||
}
|
||||
st->pin = pin;
|
||||
with_view_model(
|
||||
bad_kb->view,
|
||||
BadKbModel * model,
|
||||
@@ -223,3 +232,18 @@ void bad_kb_set_state(BadKb* bad_kb, BadKbState* st) {
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
bool bad_kb_is_idle_state(BadKb* bad_kb) {
|
||||
bool is_idle = false;
|
||||
with_view_model(
|
||||
bad_kb->view,
|
||||
BadKbModel * model,
|
||||
{
|
||||
if((model->state.state == BadKbStateIdle) || (model->state.state == BadKbStateDone) ||
|
||||
(model->state.state == BadKbStateNotConnected)) {
|
||||
is_idle = true;
|
||||
}
|
||||
},
|
||||
false);
|
||||
return is_idle;
|
||||
}
|
||||
|
||||
@@ -19,3 +19,5 @@ void bad_kb_set_file_name(BadKb* bad_kb, const char* name);
|
||||
void bad_kb_set_layout(BadKb* bad_kb, const char* layout);
|
||||
|
||||
void bad_kb_set_state(BadKb* bad_kb, BadKbState* st);
|
||||
|
||||
bool bad_kb_is_idle_state(BadKb* bad_kb);
|
||||
|
||||
@@ -8,6 +8,14 @@ static void xtreme_app_scene_protocols_bad_bk_mode_changed(VariableItem* item) {
|
||||
app->save_settings = true;
|
||||
}
|
||||
|
||||
static void xtreme_app_scene_protocols_bad_bt_remember_changed(VariableItem* item) {
|
||||
XtremeApp* app = variable_item_get_context(item);
|
||||
bool value = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, value ? "ON" : "OFF");
|
||||
XTREME_SETTINGS()->bad_bt_remember = value;
|
||||
app->save_settings = true;
|
||||
}
|
||||
|
||||
static void xtreme_app_scene_protocols_subghz_extend_changed(VariableItem* item) {
|
||||
XtremeApp* app = variable_item_get_context(item);
|
||||
app->subghz_extend = variable_item_get_current_value_index(item);
|
||||
@@ -33,6 +41,15 @@ void xtreme_app_scene_protocols_on_enter(void* context) {
|
||||
variable_item_set_current_value_index(item, xtreme_settings->bad_bt);
|
||||
variable_item_set_current_value_text(item, xtreme_settings->bad_bt ? "BT" : "USB");
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list,
|
||||
"Bad BT Remember",
|
||||
2,
|
||||
xtreme_app_scene_protocols_bad_bt_remember_changed,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, xtreme_settings->bad_bt_remember);
|
||||
variable_item_set_current_value_text(item, xtreme_settings->bad_bt_remember ? "ON" : "OFF");
|
||||
|
||||
item = variable_item_list_add(
|
||||
var_item_list, "SubGHz Extend", 2, xtreme_app_scene_protocols_subghz_extend_changed, app);
|
||||
variable_item_set_current_value_index(item, app->subghz_extend);
|
||||
|
||||
@@ -61,8 +61,11 @@ static ViewPort* bt_pin_code_view_port_alloc(Bt* bt) {
|
||||
}
|
||||
|
||||
static void bt_pin_code_show(Bt* bt, uint32_t pin_code) {
|
||||
furi_assert(bt);
|
||||
bt->pin_code = pin_code;
|
||||
notification_message(bt->notification, &sequence_display_backlight_on);
|
||||
if(bt->suppress_pin_screen) return;
|
||||
|
||||
gui_view_port_send_to_front(bt->gui, bt->pin_code_view_port);
|
||||
view_port_enabled_set(bt->pin_code_view_port, true);
|
||||
}
|
||||
@@ -76,10 +79,10 @@ static void bt_pin_code_hide(Bt* bt) {
|
||||
|
||||
static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) {
|
||||
furi_assert(bt);
|
||||
|
||||
if(bt_get_profile_pairing_method(bt) == GapPairingNone) return true;
|
||||
|
||||
bt->pin_code = pin;
|
||||
notification_message(bt->notification, &sequence_display_backlight_on);
|
||||
if(bt->suppress_pin_screen) return true;
|
||||
|
||||
FuriString* pin_str;
|
||||
dialog_message_set_icon(bt->dialog_message, XTREME_ASSETS()->I_BLE_Pairing_128x64, 0, 0);
|
||||
pin_str = furi_string_alloc_printf("Verify code\n%06lu", pin);
|
||||
@@ -154,6 +157,8 @@ Bt* bt_alloc() {
|
||||
// API evnent
|
||||
bt->api_event = furi_event_flag_alloc();
|
||||
|
||||
bt->pin = 0;
|
||||
|
||||
return bt;
|
||||
}
|
||||
|
||||
@@ -219,6 +224,7 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
Bt* bt = context;
|
||||
bool ret = false;
|
||||
bt->pin = 0;
|
||||
|
||||
if(event.type == GapEventTypeConnected) {
|
||||
// Update status bar
|
||||
@@ -275,12 +281,14 @@ static bool bt_on_gap_event_callback(GapEvent event, void* context) {
|
||||
furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||
ret = true;
|
||||
} else if(event.type == GapEventTypePinCodeShow) {
|
||||
bt->pin = event.data.pin_code;
|
||||
BtMessage message = {
|
||||
.type = BtMessageTypePinCodeShow, .data.pin_code = event.data.pin_code};
|
||||
furi_check(
|
||||
furi_message_queue_put(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||
ret = true;
|
||||
} else if(event.type == GapEventTypePinCodeVerify) {
|
||||
bt->pin = event.data.pin_code;
|
||||
ret = bt_pin_code_verify_event_handler(bt, event.data.pin_code);
|
||||
} else if(event.type == GapEventTypeUpdateMTU) {
|
||||
bt->max_packet_size = event.data.max_packet_size;
|
||||
@@ -419,17 +427,15 @@ const uint8_t* bt_get_profile_mac_address(Bt* bt) {
|
||||
return furi_hal_bt_get_profile_mac_addr(get_hal_bt_profile(bt->profile));
|
||||
}
|
||||
|
||||
bool bt_remote_rssi(Bt* bt, BtRssi* rssi) {
|
||||
bool bt_remote_rssi(Bt* bt, uint8_t* rssi) {
|
||||
furi_assert(bt);
|
||||
UNUSED(rssi);
|
||||
|
||||
uint8_t rssi_val;
|
||||
uint32_t since = furi_hal_bt_get_conn_rssi(&rssi_val);
|
||||
|
||||
if(since == 0) return false;
|
||||
|
||||
rssi->rssi = rssi_val;
|
||||
rssi->since = since;
|
||||
*rssi = rssi_val;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -451,6 +457,7 @@ void bt_disable_peer_key_update(Bt* bt) {
|
||||
}
|
||||
|
||||
void bt_enable_peer_key_update(Bt* bt) {
|
||||
furi_assert(bt);
|
||||
furi_hal_bt_set_key_storage_change_callback(bt_on_key_storage_change_callback, bt);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ const char* bt_get_profile_adv_name(Bt* bt);
|
||||
void bt_set_profile_mac_address(Bt* bt, const uint8_t mac[6]);
|
||||
const uint8_t* bt_get_profile_mac_address(Bt* bt);
|
||||
|
||||
bool bt_remote_rssi(Bt* bt, BtRssi* rssi);
|
||||
bool bt_remote_rssi(Bt* bt, uint8_t* rssi);
|
||||
|
||||
void bt_set_profile_pairing_method(Bt* bt, GapPairing pairing_method);
|
||||
GapPairing bt_get_profile_pairing_method(Bt* bt);
|
||||
|
||||
@@ -76,4 +76,6 @@ struct Bt {
|
||||
FuriEventFlag* api_event;
|
||||
BtStatusChangedCallback status_changed_cb;
|
||||
void* status_changed_ctx;
|
||||
uint32_t pin;
|
||||
bool suppress_pin_screen;
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@ void XTREME_SETTINGS_LOAD() {
|
||||
xtreme_settings->bar_borders = true; // ON
|
||||
xtreme_settings->bar_background = false; // OFF
|
||||
xtreme_settings->bad_bt = false; // USB
|
||||
xtreme_settings->bad_bt_remember = false; // OFF
|
||||
xtreme_settings->butthurt_timer = 43200; // 12 H
|
||||
xtreme_settings->sort_dirs_first = true; // ON
|
||||
xtreme_settings->dark_mode = false; // OFF
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#define MAX_PACK_NAME_LEN 32
|
||||
|
||||
#define XTREME_SETTINGS_VERSION (4)
|
||||
#define XTREME_SETTINGS_VERSION (5)
|
||||
#define XTREME_SETTINGS_PATH INT_PATH(XTREME_SETTINGS_FILE_NAME)
|
||||
#define XTREME_SETTINGS_MAGIC (0x69)
|
||||
|
||||
@@ -28,6 +28,7 @@ typedef struct {
|
||||
bool bar_borders;
|
||||
bool bar_background;
|
||||
bool bad_bt;
|
||||
bool bad_bt_remember;
|
||||
int32_t butthurt_timer;
|
||||
bool sort_dirs_first;
|
||||
bool dark_mode;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "../bt_settings_app.h"
|
||||
#include <furi_hal_bt.h>
|
||||
#include <applications/main/bad_kb/bad_kb_app_i.h>
|
||||
|
||||
void bt_settings_scene_forget_dev_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||
furi_assert(context);
|
||||
@@ -30,6 +31,11 @@ bool bt_settings_scene_forget_dev_confirm_on_event(void* context, SceneManagerEv
|
||||
consumed = scene_manager_previous_scene(app->scene_manager);
|
||||
} else if(event.event == DialogExResultRight) {
|
||||
bt_forget_bonded_devices(app->bt);
|
||||
// also removes keys of badkb bonded devices
|
||||
bt_keys_storage_set_storage_path(app->bt, BAD_KB_APP_PATH_BOUND_KEYS_FILE);
|
||||
bt_forget_bonded_devices(app->bt);
|
||||
bt_keys_storage_set_default_path(app->bt);
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, BtSettingsAppSceneForgetDevSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ Function,+,bt_get_profile_mac_address,const uint8_t*,Bt*
|
||||
Function,+,bt_get_profile_pairing_method,GapPairing,Bt*
|
||||
Function,+,bt_keys_storage_set_default_path,void,Bt*
|
||||
Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*"
|
||||
Function,+,bt_remote_rssi,_Bool,"Bt*, BtRssi*"
|
||||
Function,+,bt_remote_rssi,_Bool,"Bt*, uint8_t*"
|
||||
Function,+,bt_set_profile,_Bool,"Bt*, BtProfile"
|
||||
Function,+,bt_set_profile_adv_name,void,"Bt*, const char*, ..."
|
||||
Function,+,bt_set_profile_mac_address,void,"Bt*, const uint8_t[6]"
|
||||
|
||||
|
@@ -373,6 +373,7 @@ static void gap_init_svc(Gap* gap) {
|
||||
bool keypress_supported = false;
|
||||
uint8_t conf_mitm = CFG_MITM_PROTECTION;
|
||||
uint8_t conf_used_fixed_pin = CFG_USED_FIXED_PIN;
|
||||
bool conf_bonding = gap->config->bonding_mode;
|
||||
if(gap->config->pairing_method == GapPairingPinCodeShow) {
|
||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_ONLY);
|
||||
} else if(gap->config->pairing_method == GapPairingPinCodeVerifyYesNo) {
|
||||
@@ -382,6 +383,7 @@ static void gap_init_svc(Gap* gap) {
|
||||
// Just works pairing method (IOS accept it, it seems android and linux doesn't)
|
||||
conf_mitm = 0;
|
||||
conf_used_fixed_pin = 0;
|
||||
conf_bonding = false;
|
||||
// if just works isn't supported, we want the numeric comparaison method
|
||||
aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
|
||||
keypress_supported = true;
|
||||
@@ -389,7 +391,7 @@ static void gap_init_svc(Gap* gap) {
|
||||
|
||||
// Setup authentication
|
||||
aci_gap_set_authentication_requirement(
|
||||
gap->config->bonding_mode,
|
||||
conf_bonding,
|
||||
conf_mitm,
|
||||
CFG_SC_SUPPORT,
|
||||
keypress_supported,
|
||||
@@ -515,16 +517,16 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
|
||||
gap->advertise_timer = furi_timer_alloc(gap_advetise_timer_callback, FuriTimerTypeOnce, NULL);
|
||||
// Initialization of GATT & GAP layer
|
||||
gap->service.adv_name = config->adv_name;
|
||||
FURI_LOG_I(TAG, "Advertising name: %s", &(gap->service.adv_name[1]));
|
||||
FURI_LOG_I(
|
||||
FURI_LOG_D(TAG, "Advertising name: %s", &(gap->service.adv_name[1]));
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
"MAC @ : %02X:%02X:%02X:%02X:%02X:%02X",
|
||||
config->mac_address[0],
|
||||
config->mac_address[1],
|
||||
config->mac_address[2],
|
||||
config->mac_address[3],
|
||||
config->mac_address[5],
|
||||
config->mac_address[4],
|
||||
config->mac_address[5]);
|
||||
config->mac_address[3],
|
||||
config->mac_address[2],
|
||||
config->mac_address[1],
|
||||
config->mac_address[0]);
|
||||
gap_init_svc(gap);
|
||||
// Initialization of the BLE Services
|
||||
SVCCTL_Init();
|
||||
|
||||
@@ -209,6 +209,12 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
|
||||
profile_config[profile].config.mac_address,
|
||||
furi_hal_version_get_ble_mac(),
|
||||
sizeof(profile_config[profile].config.mac_address));
|
||||
// Set advertise name
|
||||
strlcpy(
|
||||
profile_config[profile].config.adv_name,
|
||||
furi_hal_version_get_ble_local_device_name_ptr(),
|
||||
FURI_HAL_VERSION_DEVICE_NAME_LENGTH);
|
||||
|
||||
config->adv_service_uuid |= furi_hal_version_get_hw_color();
|
||||
} else if(profile == FuriHalBtProfileHidKeyboard) {
|
||||
// Change MAC address for HID profile
|
||||
@@ -218,8 +224,11 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb,
|
||||
}
|
||||
// Change name Flipper -> Control
|
||||
if(strlen(&config->adv_name[1]) == 0) {
|
||||
const char* clicker_str = "Control";
|
||||
memcpy(&config->adv_name[1], clicker_str, strlen(clicker_str));
|
||||
snprintf(
|
||||
&config->adv_name[1],
|
||||
strlen("Control ") + FURI_HAL_VERSION_DEVICE_NAME_LENGTH,
|
||||
"Control %s",
|
||||
furi_hal_version_get_ble_local_device_name_ptr());
|
||||
}
|
||||
}
|
||||
if(!gap_init(config, event_cb, context)) {
|
||||
@@ -470,11 +479,18 @@ void furi_hal_bt_set_profile_adv_name(
|
||||
furi_assert(profile < FuriHalBtProfileNumber);
|
||||
furi_assert(name);
|
||||
|
||||
profile_config[profile].config.adv_name[0] = 0x09;
|
||||
memcpy(
|
||||
&(profile_config[profile].config.adv_name[1]),
|
||||
name,
|
||||
FURI_HAL_VERSION_DEVICE_NAME_LENGTH - 1);
|
||||
if(strlen(name) == 0) {
|
||||
memset(
|
||||
&(profile_config[profile].config.adv_name[1]),
|
||||
0,
|
||||
strlen(&(profile_config[profile].config.adv_name[1])));
|
||||
} else {
|
||||
profile_config[profile].config.adv_name[0] = AD_TYPE_COMPLETE_LOCAL_NAME;
|
||||
memcpy(
|
||||
&(profile_config[profile].config.adv_name[1]),
|
||||
name,
|
||||
FURI_HAL_VERSION_DEVICE_NAME_LENGTH - 1);
|
||||
}
|
||||
}
|
||||
|
||||
const char* furi_hal_bt_get_profile_adv_name(FuriHalBtProfile profile) {
|
||||
|
||||
Reference in New Issue
Block a user