diff --git a/applications/main/bad_usb/application.fam b/applications/main/bad_usb/application.fam index 9844e248df9..8d3909fccc6 100644 --- a/applications/main/bad_usb/application.fam +++ b/applications/main/bad_usb/application.fam @@ -7,7 +7,7 @@ App( icon="A_BadUsb_14", order=70, resources="resources", - fap_libs=["assets"], + fap_libs=["assets", "ble_profile"], fap_icon="icon.png", fap_category="USB", ) diff --git a/applications/main/bad_usb/bad_usb_app.c b/applications/main/bad_usb/bad_usb_app.c index 1ee92bdf3f1..eda702cf4d6 100644 --- a/applications/main/bad_usb/bad_usb_app.c +++ b/applications/main/bad_usb/bad_usb_app.c @@ -35,6 +35,7 @@ static void bad_usb_load_settings(BadUsbApp* app) { FuriString* temp_str = furi_string_alloc(); uint32_t version = 0; + uint32_t interface = 0; if(flipper_format_file_open_existing(fff, BAD_USB_SETTINGS_PATH)) { do { @@ -44,6 +45,8 @@ static void bad_usb_load_settings(BadUsbApp* app) { break; if(!flipper_format_read_string(fff, "layout", temp_str)) break; + if(!flipper_format_read_uint32(fff, "interface", &interface, 1)) break; + if(interface > BadUsbHidInterfaceBle) break; state = true; } while(0); @@ -53,6 +56,7 @@ static void bad_usb_load_settings(BadUsbApp* app) { if(state) { furi_string_set(app->keyboard_layout, temp_str); + app->interface = interface; Storage* fs_api = furi_record_open(RECORD_STORAGE); FileInfo layout_file_info; @@ -64,6 +68,7 @@ static void bad_usb_load_settings(BadUsbApp* app) { } } else { furi_string_set(app->keyboard_layout, BAD_USB_SETTINGS_DEFAULT_LAYOUT); + app->interface = BadUsbHidInterfaceUsb; } furi_string_free(temp_str); @@ -79,6 +84,9 @@ static void bad_usb_save_settings(BadUsbApp* app) { fff, BAD_USB_SETTINGS_FILE_TYPE, BAD_USB_SETTINGS_VERSION)) break; if(!flipper_format_write_string(fff, "layout", app->keyboard_layout)) break; + uint32_t interface_id = app->interface; + if(!flipper_format_write_uint32(fff, "interface", (const uint32_t*)&interface_id, 1)) + break; } while(0); } @@ -86,6 +94,11 @@ static void bad_usb_save_settings(BadUsbApp* app) { furi_record_close(RECORD_STORAGE); } +void bad_usb_set_interface(BadUsbApp* app, BadUsbHidInterface interface) { + app->interface = interface; + bad_usb_view_set_interface(app->bad_usb_view, interface); +} + BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* app = malloc(sizeof(BadUsbApp)); @@ -117,7 +130,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { // Custom Widget app->widget = widget_alloc(); view_dispatcher_add_view( - app->view_dispatcher, BadUsbAppViewError, widget_get_view(app->widget)); + app->view_dispatcher, BadUsbAppViewWidget, widget_get_view(app->widget)); + + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view(app->view_dispatcher, BadUsbAppViewPopup, popup_get_view(app->popup)); app->var_item_list = variable_item_list_alloc(); view_dispatcher_add_view( @@ -163,9 +180,13 @@ void bad_usb_app_free(BadUsbApp* app) { bad_usb_view_free(app->bad_usb_view); // Custom Widget - view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewError); + view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewWidget); widget_free(app->widget); + // Popup + view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewPopup); + popup_free(app->popup); + // Config menu view_dispatcher_remove_view(app->view_dispatcher, BadUsbAppViewConfig); variable_item_list_free(app->var_item_list); diff --git a/applications/main/bad_usb/bad_usb_app_i.h b/applications/main/bad_usb/bad_usb_app_i.h index e63d0044c00..b34bd5de699 100644 --- a/applications/main/bad_usb/bad_usb_app_i.h +++ b/applications/main/bad_usb/bad_usb_app_i.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "views/bad_usb_view.h" #include @@ -33,6 +34,7 @@ struct BadUsbApp { NotificationApp* notifications; DialogsApp* dialogs; Widget* widget; + Popup* popup; VariableItemList* var_item_list; BadUsbAppError error; @@ -41,11 +43,15 @@ struct BadUsbApp { BadUsb* bad_usb_view; BadUsbScript* bad_usb_script; + BadUsbHidInterface interface; FuriHalUsbInterface* usb_if_prev; }; typedef enum { - BadUsbAppViewError, + BadUsbAppViewWidget, + BadUsbAppViewPopup, BadUsbAppViewWork, BadUsbAppViewConfig, } BadUsbAppView; + +void bad_usb_set_interface(BadUsbApp* app, BadUsbHidInterface interface); diff --git a/applications/main/bad_usb/helpers/bad_usb_hid.c b/applications/main/bad_usb/helpers/bad_usb_hid.c index dcba7b5e932..5d7076314af 100644 --- a/applications/main/bad_usb/helpers/bad_usb_hid.c +++ b/applications/main/bad_usb/helpers/bad_usb_hid.c @@ -1,9 +1,12 @@ #include "bad_usb_hid.h" #include +#include #include #define TAG "BadUSB HID" +#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" + void* hid_usb_init(FuriHalUsbHidConfig* hid_cfg) { furi_check(furi_hal_usb_set_config(&usb_hid, hid_cfg)); return NULL; @@ -69,6 +72,155 @@ static const BadUsbHidApi hid_api_usb = { .release_all = hid_usb_release_all, .get_led_state = hid_usb_get_led_state, }; -const BadUsbHidApi* bad_usb_hid_get_interface() { - return &hid_api_usb; + +typedef struct { + Bt* bt; + FuriHalBleProfileBase* profile; + HidStateCallback state_callback; + void* callback_context; + bool is_connected; +} BleHidInstance; + +static const BleProfileHidParams ble_hid_params = { + .device_name_prefix = "BadUSB", + .mac_xor = 0x0002, +}; + +static void hid_ble_connection_status_callback(BtStatus status, void* context) { + furi_assert(context); + BleHidInstance* ble_hid = context; + ble_hid->is_connected = (status == BtStatusConnected); + if(ble_hid->state_callback) { + ble_hid->state_callback(ble_hid->is_connected, ble_hid->callback_context); + } +} + +void* hid_ble_init(FuriHalUsbHidConfig* hid_cfg) { + UNUSED(hid_cfg); + BleHidInstance* ble_hid = malloc(sizeof(BleHidInstance)); + ble_hid->bt = furi_record_open(RECORD_BT); + bt_disconnect(ble_hid->bt); + + // Wait 2nd core to update nvm storage + furi_delay_ms(200); + + bt_keys_storage_set_storage_path(ble_hid->bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); + + ble_hid->profile = bt_profile_start(ble_hid->bt, ble_profile_hid, (void*)&ble_hid_params); + furi_check(ble_hid->profile); + + furi_hal_bt_start_advertising(); + + bt_set_status_changed_callback(ble_hid->bt, hid_ble_connection_status_callback, ble_hid); + + return ble_hid; +} + +void hid_ble_deinit(void* inst) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + + bt_set_status_changed_callback(ble_hid->bt, NULL, NULL); + bt_disconnect(ble_hid->bt); + + // Wait 2nd core to update nvm storage + furi_delay_ms(200); + bt_keys_storage_set_default_path(ble_hid->bt); + + furi_check(bt_profile_restore_default(ble_hid->bt)); + furi_record_close(RECORD_BT); + free(ble_hid); +} + +void hid_ble_set_state_callback(void* inst, HidStateCallback cb, void* context) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + ble_hid->state_callback = cb; + ble_hid->callback_context = context; +} + +bool hid_ble_is_connected(void* inst) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + return ble_hid->is_connected; +} + +bool hid_ble_kb_press(void* inst, uint16_t button) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + return ble_profile_hid_kb_press(ble_hid->profile, button); +} + +bool hid_ble_kb_release(void* inst, uint16_t button) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + return ble_profile_hid_kb_release(ble_hid->profile, button); +} + +bool hid_ble_consumer_press(void* inst, uint16_t button) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + return ble_profile_hid_consumer_key_press(ble_hid->profile, button); +} + +bool hid_ble_consumer_release(void* inst, uint16_t button) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + return ble_profile_hid_consumer_key_release(ble_hid->profile, button); +} + +bool hid_ble_release_all(void* inst) { + BleHidInstance* ble_hid = inst; + furi_assert(ble_hid); + bool state = ble_profile_hid_kb_release_all(ble_hid->profile); + state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile); + return state; +} + +uint8_t hid_ble_get_led_state(void* inst) { + UNUSED(inst); + FURI_LOG_W(TAG, "hid_ble_get_led_state not implemented"); + return 0; +} + +static const BadUsbHidApi hid_api_ble = { + .init = hid_ble_init, + .deinit = hid_ble_deinit, + .set_state_callback = hid_ble_set_state_callback, + .is_connected = hid_ble_is_connected, + + .kb_press = hid_ble_kb_press, + .kb_release = hid_ble_kb_release, + .consumer_press = hid_ble_consumer_press, + .consumer_release = hid_ble_consumer_release, + .release_all = hid_ble_release_all, + .get_led_state = hid_ble_get_led_state, +}; + +const BadUsbHidApi* bad_usb_hid_get_interface(BadUsbHidInterface interface) { + if(interface == BadUsbHidInterfaceUsb) { + return &hid_api_usb; + } else { + return &hid_api_ble; + } +} + +void bad_usb_hid_ble_remove_pairing(void) { + Bt* bt = furi_record_open(RECORD_BT); + bt_disconnect(bt); + + // Wait 2nd core to update nvm storage + furi_delay_ms(200); + + furi_hal_bt_stop_advertising(); + + bt_keys_storage_set_storage_path(bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); + bt_forget_bonded_devices(bt); + + // Wait 2nd core to update nvm storage + furi_delay_ms(200); + bt_keys_storage_set_default_path(bt); + + furi_check(bt_profile_restore_default(bt)); + furi_record_close(RECORD_BT); } diff --git a/applications/main/bad_usb/helpers/bad_usb_hid.h b/applications/main/bad_usb/helpers/bad_usb_hid.h index feaaacd5415..71d3a58e793 100644 --- a/applications/main/bad_usb/helpers/bad_usb_hid.h +++ b/applications/main/bad_usb/helpers/bad_usb_hid.h @@ -7,6 +7,11 @@ extern "C" { #include #include +typedef enum { + BadUsbHidInterfaceUsb, + BadUsbHidInterfaceBle, +} BadUsbHidInterface; + typedef struct { void* (*init)(FuriHalUsbHidConfig* hid_cfg); void (*deinit)(void* inst); @@ -21,7 +26,7 @@ typedef struct { uint8_t (*get_led_state)(void* inst); } BadUsbHidApi; -const BadUsbHidApi* bad_usb_hid_get_interface(); +const BadUsbHidApi* bad_usb_hid_get_interface(BadUsbHidInterface interface); void bad_usb_hid_ble_remove_pairing(void); diff --git a/applications/main/bad_usb/helpers/ducky_script.c b/applications/main/bad_usb/helpers/ducky_script.c index d730fdba4df..ccc3caa811b 100644 --- a/applications/main/bad_usb/helpers/ducky_script.c +++ b/applications/main/bad_usb/helpers/ducky_script.c @@ -650,7 +650,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, BadUsbHidInterface interface) { furi_assert(file_path); BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); @@ -660,7 +660,7 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path) { bad_usb->st.state = BadUsbStateInit; bad_usb->st.error[0] = '\0'; - bad_usb->hid = bad_usb_hid_get_interface(); + bad_usb->hid = bad_usb_hid_get_interface(interface); bad_usb->thread = furi_thread_alloc_ex("BadUsbWorker", 2048, bad_usb_worker, bad_usb); furi_thread_start(bad_usb->thread); diff --git a/applications/main/bad_usb/helpers/ducky_script.h b/applications/main/bad_usb/helpers/ducky_script.h index 43969d7b67d..9519623f604 100644 --- a/applications/main/bad_usb/helpers/ducky_script.h +++ b/applications/main/bad_usb/helpers/ducky_script.h @@ -34,7 +34,7 @@ typedef struct { typedef struct BadUsbScript BadUsbScript; -BadUsbScript* bad_usb_script_open(FuriString* file_path); +BadUsbScript* bad_usb_script_open(FuriString* file_path, BadUsbHidInterface interface); void bad_usb_script_close(BadUsbScript* bad_usb); diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config.c b/applications/main/bad_usb/scenes/bad_usb_scene_config.c new file mode 100644 index 00000000000..ae440cade9e --- /dev/null +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config.c @@ -0,0 +1,59 @@ +#include "../bad_usb_app_i.h" + +enum SubmenuIndex { + ConfigIndexKeyboardLayout, + ConfigIndexBleUnpair, +}; + +void bad_usb_scene_config_select_callback(void* context, uint32_t index) { + BadUsbApp* bad_usb = context; + + view_dispatcher_send_custom_event(bad_usb->view_dispatcher, index); +} + +static void draw_menu(BadUsbApp* bad_usb) { + VariableItemList* var_item_list = bad_usb->var_item_list; + + variable_item_list_reset(var_item_list); + + variable_item_list_add(var_item_list, "Keyboard Layout (global)", 0, NULL, NULL); + + variable_item_list_add(var_item_list, "Remove Pairing", 0, NULL, NULL); +} + +void bad_usb_scene_config_on_enter(void* context) { + BadUsbApp* bad_usb = context; + VariableItemList* var_item_list = bad_usb->var_item_list; + + variable_item_list_set_enter_callback( + var_item_list, bad_usb_scene_config_select_callback, bad_usb); + draw_menu(bad_usb); + variable_item_list_set_selected_item(var_item_list, 0); + + 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) { + consumed = true; + if(event.event == ConfigIndexKeyboardLayout) { + scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfigLayout); + } else if(event.event == ConfigIndexBleUnpair) { + scene_manager_next_scene(bad_usb->scene_manager, BadUsbSceneConfirmUnpair); + } else { + furi_crash("Unknown key type"); + } + } + + return consumed; +} + +void bad_usb_scene_config_on_exit(void* context) { + BadUsbApp* bad_usb = context; + VariableItemList* var_item_list = bad_usb->var_item_list; + + variable_item_list_reset(var_item_list); +} diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_config.h b/applications/main/bad_usb/scenes/bad_usb_scene_config.h index e640bb556b5..3d1b8b1a7a2 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_config.h +++ b/applications/main/bad_usb/scenes/bad_usb_scene_config.h @@ -1,4 +1,7 @@ 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_layout, ConfigLayout) +ADD_SCENE(bad_usb, confirm_unpair, ConfirmUnpair) +ADD_SCENE(bad_usb, unpair_done, UnpairDone) diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_confirm_unpair.c b/applications/main/bad_usb/scenes/bad_usb_scene_confirm_unpair.c similarity index 51% rename from applications/system/bad_ble/scenes/bad_ble_scene_confirm_unpair.c rename to applications/main/bad_usb/scenes/bad_usb_scene_confirm_unpair.c index 63f1e92cf25..b8fd993e2e7 100644 --- a/applications/system/bad_ble/scenes/bad_ble_scene_confirm_unpair.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_confirm_unpair.c @@ -1,42 +1,42 @@ -#include "../bad_ble_app_i.h" +#include "../bad_usb_app_i.h" -void bad_ble_scene_confirm_unpair_widget_callback( +void bad_usb_scene_confirm_unpair_widget_callback( GuiButtonType type, InputType input_type, void* context) { UNUSED(input_type); SceneManagerEvent event = {.type = SceneManagerEventTypeCustom, .event = type}; - bad_ble_scene_confirm_unpair_on_event(context, event); + bad_usb_scene_confirm_unpair_on_event(context, event); } -void bad_ble_scene_confirm_unpair_on_enter(void* context) { - BadBleApp* bad_ble = context; - Widget* widget = bad_ble->widget; +void bad_usb_scene_confirm_unpair_on_enter(void* context) { + BadUsbApp* bad_usb = context; + Widget* widget = bad_usb->widget; widget_add_button_element( - widget, GuiButtonTypeLeft, "Cancel", bad_ble_scene_confirm_unpair_widget_callback, context); + widget, GuiButtonTypeLeft, "Cancel", bad_usb_scene_confirm_unpair_widget_callback, context); widget_add_button_element( widget, GuiButtonTypeRight, "Unpair", - bad_ble_scene_confirm_unpair_widget_callback, + bad_usb_scene_confirm_unpair_widget_callback, context); widget_add_text_box_element( widget, 0, 0, 128, 64, AlignCenter, AlignTop, "\e#Unpair the Device?\e#\n", false); - view_dispatcher_switch_to_view(bad_ble->view_dispatcher, BadBleAppViewWidget); + view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewWidget); } -bool bad_ble_scene_confirm_unpair_on_event(void* context, SceneManagerEvent event) { - BadBleApp* bad_ble = context; - SceneManager* scene_manager = bad_ble->scene_manager; +bool bad_usb_scene_confirm_unpair_on_event(void* context, SceneManagerEvent event) { + BadUsbApp* bad_usb = context; + SceneManager* scene_manager = bad_usb->scene_manager; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == GuiButtonTypeRight) { - scene_manager_next_scene(scene_manager, BadBleSceneUnpairDone); + scene_manager_next_scene(scene_manager, BadUsbSceneUnpairDone); } else if(event.event == GuiButtonTypeLeft) { scene_manager_previous_scene(scene_manager); } @@ -45,9 +45,9 @@ bool bad_ble_scene_confirm_unpair_on_event(void* context, SceneManagerEvent even return consumed; } -void bad_ble_scene_confirm_unpair_on_exit(void* context) { - BadBleApp* bad_ble = context; - Widget* widget = bad_ble->widget; +void bad_usb_scene_confirm_unpair_on_exit(void* context) { + BadUsbApp* bad_usb = context; + Widget* widget = bad_usb->widget; widget_reset(widget); } diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_error.c b/applications/main/bad_usb/scenes/bad_usb_scene_error.c index 9d3a44f12f9..ea7f797671e 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_error.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_error.c @@ -43,7 +43,7 @@ void bad_usb_scene_error_on_enter(void* context) { "Disconnect from\nPC or phone to\nuse this function."); } - view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewError); + view_dispatcher_switch_to_view(app->view_dispatcher, BadUsbAppViewWidget); } bool bad_usb_scene_error_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_unpair_done.c b/applications/main/bad_usb/scenes/bad_usb_scene_unpair_done.c new file mode 100644 index 00000000000..9583f9bfba3 --- /dev/null +++ b/applications/main/bad_usb/scenes/bad_usb_scene_unpair_done.c @@ -0,0 +1,39 @@ +#include "../bad_usb_app_i.h" + +static void bad_usb_scene_unpair_done_popup_callback(void* context) { + BadUsbApp* bad_usb = context; + scene_manager_search_and_switch_to_previous_scene(bad_usb->scene_manager, BadUsbSceneConfig); +} + +void bad_usb_scene_unpair_done_on_enter(void* context) { + BadUsbApp* bad_usb = context; + Popup* popup = bad_usb->popup; + + bad_usb_hid_ble_remove_pairing(); + + popup_set_icon(popup, 48, 4, &I_DolphinDone_80x58); + popup_set_header(popup, "Done", 20, 19, AlignLeft, AlignBottom); + popup_set_callback(popup, bad_usb_scene_unpair_done_popup_callback); + popup_set_context(popup, bad_usb); + popup_set_timeout(popup, 1500); + popup_enable_timeout(popup); + + view_dispatcher_switch_to_view(bad_usb->view_dispatcher, BadUsbAppViewPopup); +} + +bool bad_usb_scene_unpair_done_on_event(void* context, SceneManagerEvent event) { + BadUsbApp* bad_usb = context; + UNUSED(bad_usb); + UNUSED(event); + bool consumed = false; + + return consumed; +} + +void bad_usb_scene_unpair_done_on_exit(void* context) { + BadUsbApp* bad_usb = context; + Popup* popup = bad_usb->popup; + UNUSED(popup); + + popup_reset(popup); +} diff --git a/applications/main/bad_usb/scenes/bad_usb_scene_work.c b/applications/main/bad_usb/scenes/bad_usb_scene_work.c index 0afc056b622..0382b0f8ea6 100644 --- a/applications/main/bad_usb/scenes/bad_usb_scene_work.c +++ b/applications/main/bad_usb/scenes/bad_usb_scene_work.c @@ -20,14 +20,27 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { bad_usb_script_close(app->bad_usb_script); app->bad_usb_script = NULL; - scene_manager_next_scene(app->scene_manager, BadUsbSceneConfigLayout); + if(app->interface == BadUsbHidInterfaceBle) { + scene_manager_next_scene(app->scene_manager, BadUsbSceneConfig); + } else { + scene_manager_next_scene(app->scene_manager, BadUsbSceneConfigLayout); + } } consumed = true; } else if(event.event == InputKeyOk) { bad_usb_script_start_stop(app->bad_usb_script); consumed = true; } else if(event.event == InputKeyRight) { - bad_usb_script_pause_resume(app->bad_usb_script); + if(bad_usb_view_is_idle_state(app->bad_usb_view)) { + bad_usb_set_interface( + app, + app->interface == BadUsbHidInterfaceBle ? BadUsbHidInterfaceUsb : + BadUsbHidInterfaceBle); + bad_usb_script_close(app->bad_usb_script); + app->bad_usb_script = bad_usb_script_open(app->file_path, app->interface); + } else { + bad_usb_script_pause_resume(app->bad_usb_script); + } consumed = true; } } else if(event.type == SceneManagerEventTypeTick) { @@ -39,7 +52,9 @@ bool bad_usb_scene_work_on_event(void* context, SceneManagerEvent event) { void bad_usb_scene_work_on_enter(void* context) { BadUsbApp* app = context; - app->bad_usb_script = bad_usb_script_open(app->file_path); + bad_usb_view_set_interface(app->bad_usb_view, app->interface); + + app->bad_usb_script = bad_usb_script_open(app->file_path, app->interface); bad_usb_script_set_keyboard_layout(app->bad_usb_script, app->keyboard_layout); FuriString* file_name; diff --git a/applications/main/bad_usb/views/bad_usb_view.c b/applications/main/bad_usb/views/bad_usb_view.c index 7fb0b1434e6..1a6f77958d4 100644 --- a/applications/main/bad_usb/views/bad_usb_view.c +++ b/applications/main/bad_usb/views/bad_usb_view.c @@ -18,6 +18,7 @@ typedef struct { BadUsbState state; bool pause_wait; uint8_t anim_frame; + BadUsbHidInterface interface; } BadUsbModel; static void bad_usb_draw_callback(Canvas* canvas, void* _model) { @@ -40,14 +41,24 @@ static void bad_usb_draw_callback(Canvas* canvas, void* _model) { furi_string_reset(disp_str); - canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22); + if(model->interface == BadUsbHidInterfaceBle) { + canvas_draw_icon(canvas, 22, 24, &I_Bad_BLE_48x22); + } else { + canvas_draw_icon(canvas, 22, 24, &I_UsbTree_48x22); + } BadUsbWorkerState state = model->state.state; if((state == BadUsbStateIdle) || (state == BadUsbStateDone) || (state == BadUsbStateNotConnected)) { elements_button_center(canvas, "Run"); - elements_button_left(canvas, "Layout"); + if(model->interface == BadUsbHidInterfaceBle) { + elements_button_right(canvas, "USB"); + elements_button_left(canvas, "Config"); + } else { + elements_button_right(canvas, "BLE"); + elements_button_left(canvas, "Layout"); + } } else if((state == BadUsbStateRunning) || (state == BadUsbStateDelay)) { elements_button_center(canvas, "Stop"); if(!model->pause_wait) { @@ -266,6 +277,10 @@ void bad_usb_view_set_state(BadUsb* bad_usb, BadUsbState* st) { true); } +void bad_usb_view_set_interface(BadUsb* bad_usb, BadUsbHidInterface interface) { + with_view_model(bad_usb->view, BadUsbModel * model, { model->interface = interface; }, true); +} + bool bad_usb_view_is_idle_state(BadUsb* bad_usb) { bool is_idle = false; with_view_model( diff --git a/applications/main/bad_usb/views/bad_usb_view.h b/applications/main/bad_usb/views/bad_usb_view.h index 45f13d650b7..bca2f4bc083 100644 --- a/applications/main/bad_usb/views/bad_usb_view.h +++ b/applications/main/bad_usb/views/bad_usb_view.h @@ -23,4 +23,6 @@ void bad_usb_view_set_layout(BadUsb* bad_usb, const char* layout); void bad_usb_view_set_state(BadUsb* bad_usb, BadUsbState* st); +void bad_usb_view_set_interface(BadUsb* bad_usb, BadUsbHidInterface interface); + bool bad_usb_view_is_idle_state(BadUsb* bad_usb); diff --git a/applications/system/bad_ble/application.fam b/applications/system/bad_ble/application.fam deleted file mode 100644 index e00e6eefccf..00000000000 --- a/applications/system/bad_ble/application.fam +++ /dev/null @@ -1,12 +0,0 @@ -App( - appid="bad_ble", - name="Bad BLE", - apptype=FlipperAppType.EXTERNAL, - entry_point="bad_ble_app", - stack_size=2 * 1024, - icon="A_BadUsb_14", - fap_libs=["assets", "ble_profile"], - fap_icon="icon.png", - fap_icon_assets="assets", - fap_category="Bluetooth", -) diff --git a/applications/system/bad_ble/bad_ble_app.c b/applications/system/bad_ble/bad_ble_app.c deleted file mode 100644 index f243371986a..00000000000 --- a/applications/system/bad_ble/bad_ble_app.c +++ /dev/null @@ -1,196 +0,0 @@ -#include "bad_ble_app_i.h" -#include -#include -#include -#include -#include - -#define BAD_BLE_SETTINGS_PATH BAD_BLE_APP_BASE_FOLDER "/.badble.settings" -#define BAD_BLE_SETTINGS_FILE_TYPE "Flipper BadBLE Settings File" -#define BAD_BLE_SETTINGS_VERSION 1 -#define BAD_BLE_SETTINGS_DEFAULT_LAYOUT BAD_BLE_APP_PATH_LAYOUT_FOLDER "/en-US.kl" - -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) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff = flipper_format_file_alloc(storage); - bool state = false; - - FuriString* temp_str = furi_string_alloc(); - uint32_t version = 0; - - if(flipper_format_file_open_existing(fff, BAD_BLE_SETTINGS_PATH)) { - do { - if(!flipper_format_read_header(fff, temp_str, &version)) break; - if((strcmp(furi_string_get_cstr(temp_str), BAD_BLE_SETTINGS_FILE_TYPE) != 0) || - (version != BAD_BLE_SETTINGS_VERSION)) - break; - - if(!flipper_format_read_string(fff, "layout", temp_str)) break; - - state = true; - } while(0); - } - flipper_format_free(fff); - furi_record_close(RECORD_STORAGE); - - if(state) { - furi_string_set(app->keyboard_layout, temp_str); - - Storage* fs_api = furi_record_open(RECORD_STORAGE); - FileInfo layout_file_info; - FS_Error file_check_err = storage_common_stat( - fs_api, furi_string_get_cstr(app->keyboard_layout), &layout_file_info); - furi_record_close(RECORD_STORAGE); - if((file_check_err != FSE_OK) || (layout_file_info.size != 256)) { - furi_string_set(app->keyboard_layout, BAD_BLE_SETTINGS_DEFAULT_LAYOUT); - } - } else { - furi_string_set(app->keyboard_layout, BAD_BLE_SETTINGS_DEFAULT_LAYOUT); - } - - furi_string_free(temp_str); -} - -static void bad_ble_save_settings(BadBleApp* app) { - Storage* storage = furi_record_open(RECORD_STORAGE); - FlipperFormat* fff = flipper_format_file_alloc(storage); - - if(flipper_format_file_open_always(fff, BAD_BLE_SETTINGS_PATH)) { - do { - if(!flipper_format_write_header_cstr( - fff, BAD_BLE_SETTINGS_FILE_TYPE, BAD_BLE_SETTINGS_VERSION)) - break; - if(!flipper_format_write_string(fff, "layout", app->keyboard_layout)) break; - } while(0); - } - - flipper_format_free(fff); - furi_record_close(RECORD_STORAGE); -} - -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(); - 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); - - // Custom Widget - app->widget = widget_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBleAppViewWidget, widget_get_view(app->widget)); - - // Popup - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, BadBleAppViewPopup, popup_get_view(app->popup)); - - app->var_item_list = variable_item_list_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - BadBleAppViewConfig, - variable_item_list_get_view(app->var_item_list)); - - app->bad_ble_view = bad_ble_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, BadBleAppViewWork, bad_ble_view_get_view(app->bad_ble_view)); - - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - if(!furi_string_empty(app->file_path)) { - 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_view_free(app->bad_ble_view); - - // Custom Widget - view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewWidget); - widget_free(app->widget); - - // Popup - view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewPopup); - popup_free(app->popup); - - // Config menu - view_dispatcher_remove_view(app->view_dispatcher, BadBleAppViewConfig); - variable_item_list_free(app->var_item_list); - - // 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); - - 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; -} diff --git a/applications/system/bad_ble/bad_ble_app.h b/applications/system/bad_ble/bad_ble_app.h deleted file mode 100644 index 11954836e56..00000000000 --- a/applications/system/bad_ble/bad_ble_app.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BadBleApp BadBleApp; - -#ifdef __cplusplus -} -#endif diff --git a/applications/system/bad_ble/bad_ble_app_i.h b/applications/system/bad_ble/bad_ble_app_i.h deleted file mode 100644 index d1f739bebbc..00000000000 --- a/applications/system/bad_ble/bad_ble_app_i.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "bad_ble_app.h" -#include "scenes/bad_ble_scene.h" -#include "helpers/ducky_script.h" -#include "helpers/bad_ble_hid.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "views/bad_ble_view.h" - -#define BAD_BLE_APP_BASE_FOLDER EXT_PATH("badusb") -#define BAD_BLE_APP_PATH_LAYOUT_FOLDER BAD_BLE_APP_BASE_FOLDER "/assets/layouts" -#define BAD_BLE_APP_SCRIPT_EXTENSION ".txt" -#define BAD_BLE_APP_LAYOUT_EXTENSION ".kl" - -typedef enum { - BadBleAppErrorNoFiles, - BadBleAppErrorCloseRpc, -} BadBleAppError; - -struct BadBleApp { - Gui* gui; - ViewDispatcher* view_dispatcher; - SceneManager* scene_manager; - NotificationApp* notifications; - DialogsApp* dialogs; - Widget* widget; - Popup* popup; - VariableItemList* var_item_list; - - BadBleAppError error; - FuriString* file_path; - FuriString* keyboard_layout; - BadBle* bad_ble_view; - BadBleScript* bad_ble_script; - - BadBleHidInterface interface; -}; - -typedef enum { - BadBleAppViewWidget, - BadBleAppViewPopup, - BadBleAppViewWork, - BadBleAppViewConfig, -} BadBleAppView; diff --git a/applications/system/bad_ble/helpers/bad_ble_hid.c b/applications/system/bad_ble/helpers/bad_ble_hid.c deleted file mode 100644 index c34b3c64612..00000000000 --- a/applications/system/bad_ble/helpers/bad_ble_hid.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "bad_ble_hid.h" -#include -#include -#include - -#define TAG "BadBLE HID" - -#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" - -typedef struct { - Bt* bt; - FuriHalBleProfileBase* profile; - HidStateCallback state_callback; - void* callback_context; - bool is_connected; -} BleHidInstance; - -static const BleProfileHidParams ble_hid_params = { - .device_name_prefix = "BadBLE", - .mac_xor = 0x0002, -}; - -static void hid_ble_connection_status_callback(BtStatus status, void* context) { - furi_assert(context); - BleHidInstance* ble_hid = context; - ble_hid->is_connected = (status == BtStatusConnected); - if(ble_hid->state_callback) { - ble_hid->state_callback(ble_hid->is_connected, ble_hid->callback_context); - } -} - -void* hid_ble_init(FuriHalUsbHidConfig* hid_cfg) { - UNUSED(hid_cfg); - BleHidInstance* ble_hid = malloc(sizeof(BleHidInstance)); - ble_hid->bt = furi_record_open(RECORD_BT); - bt_disconnect(ble_hid->bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - - bt_keys_storage_set_storage_path(ble_hid->bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); - - ble_hid->profile = bt_profile_start(ble_hid->bt, ble_profile_hid, (void*)&ble_hid_params); - furi_check(ble_hid->profile); - - furi_hal_bt_start_advertising(); - - bt_set_status_changed_callback(ble_hid->bt, hid_ble_connection_status_callback, ble_hid); - - return ble_hid; -} - -void hid_ble_deinit(void* inst) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - - bt_set_status_changed_callback(ble_hid->bt, NULL, NULL); - bt_disconnect(ble_hid->bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - bt_keys_storage_set_default_path(ble_hid->bt); - - furi_check(bt_profile_restore_default(ble_hid->bt)); - furi_record_close(RECORD_BT); - free(ble_hid); -} - -void hid_ble_set_state_callback(void* inst, HidStateCallback cb, void* context) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - ble_hid->state_callback = cb; - ble_hid->callback_context = context; -} - -bool hid_ble_is_connected(void* inst) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - return ble_hid->is_connected; -} - -bool hid_ble_kb_press(void* inst, uint16_t button) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - return ble_profile_hid_kb_press(ble_hid->profile, button); -} - -bool hid_ble_kb_release(void* inst, uint16_t button) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - return ble_profile_hid_kb_release(ble_hid->profile, button); -} - -bool hid_ble_consumer_press(void* inst, uint16_t button) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - return ble_profile_hid_consumer_key_press(ble_hid->profile, button); -} - -bool hid_ble_consumer_release(void* inst, uint16_t button) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - return ble_profile_hid_consumer_key_release(ble_hid->profile, button); -} - -bool hid_ble_release_all(void* inst) { - BleHidInstance* ble_hid = inst; - furi_assert(ble_hid); - bool state = ble_profile_hid_kb_release_all(ble_hid->profile); - state &= ble_profile_hid_consumer_key_release_all(ble_hid->profile); - return state; -} - -uint8_t hid_ble_get_led_state(void* inst) { - UNUSED(inst); - FURI_LOG_W(TAG, "hid_ble_get_led_state not implemented"); - return 0; -} - -static const BadBleHidApi hid_api_ble = { - .init = hid_ble_init, - .deinit = hid_ble_deinit, - .set_state_callback = hid_ble_set_state_callback, - .is_connected = hid_ble_is_connected, - - .kb_press = hid_ble_kb_press, - .kb_release = hid_ble_kb_release, - .consumer_press = hid_ble_consumer_press, - .consumer_release = hid_ble_consumer_release, - .release_all = hid_ble_release_all, - .get_led_state = hid_ble_get_led_state, -}; - -const BadBleHidApi* bad_ble_hid_get_interface(BadBleHidInterface interface) { - UNUSED(interface); - return &hid_api_ble; -} - -void bad_ble_hid_ble_remove_pairing(void) { - Bt* bt = furi_record_open(RECORD_BT); - bt_disconnect(bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - - furi_hal_bt_stop_advertising(); - - bt_keys_storage_set_storage_path(bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); - bt_forget_bonded_devices(bt); - - // Wait 2nd core to update nvm storage - furi_delay_ms(200); - bt_keys_storage_set_default_path(bt); - - furi_check(bt_profile_restore_default(bt)); - furi_record_close(RECORD_BT); -} diff --git a/applications/system/bad_ble/helpers/bad_ble_hid.h b/applications/system/bad_ble/helpers/bad_ble_hid.h deleted file mode 100644 index b06385d6dd4..00000000000 --- a/applications/system/bad_ble/helpers/bad_ble_hid.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef enum { - BadBleHidInterfaceBle, -} BadBleHidInterface; - -typedef struct { - void* (*init)(FuriHalUsbHidConfig* hid_cfg); - void (*deinit)(void* inst); - void (*set_state_callback)(void* inst, HidStateCallback cb, void* context); - bool (*is_connected)(void* inst); - - bool (*kb_press)(void* inst, uint16_t button); - bool (*kb_release)(void* inst, uint16_t button); - bool (*consumer_press)(void* inst, uint16_t button); - bool (*consumer_release)(void* inst, uint16_t button); - bool (*release_all)(void* inst); - uint8_t (*get_led_state)(void* inst); -} BadBleHidApi; - -const BadBleHidApi* bad_ble_hid_get_interface(BadBleHidInterface interface); - -void bad_ble_hid_ble_remove_pairing(void); - -#ifdef __cplusplus -} -#endif diff --git a/applications/system/bad_ble/helpers/ducky_script.c b/applications/system/bad_ble/helpers/ducky_script.c deleted file mode 100644 index a903fbdc4d0..00000000000 --- a/applications/system/bad_ble/helpers/ducky_script.c +++ /dev/null @@ -1,716 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "ducky_script.h" -#include "ducky_script_i.h" -#include - -#define TAG "BadBle" - -#define WORKER_TAG TAG "Worker" - -#define BADUSB_ASCII_TO_KEY(script, x) \ - (((uint8_t)x < 128) ? (script->layout[(uint8_t)x]) : HID_KEYBOARD_NONE) - -typedef enum { - WorkerEvtStartStop = (1 << 0), - WorkerEvtPauseResume = (1 << 1), - WorkerEvtEnd = (1 << 2), - WorkerEvtConnect = (1 << 3), - WorkerEvtDisconnect = (1 << 4), -} WorkerEvtFlags; - -static const char ducky_cmd_id[] = {"ID"}; - -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, -}; - -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; -} - -bool ducky_is_line_end(const char chr) { - return (chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n'); -} - -uint16_t ducky_get_keycode(BadBleScript* bad_ble, const char* param, bool accept_chars) { - uint16_t keycode = ducky_get_keycode_by_name(param); - if(keycode != HID_KEYBOARD_NONE) { - return keycode; - } - - if((accept_chars) && (strlen(param) > 0)) { - return BADUSB_ASCII_TO_KEY(bad_ble, param[0]) & 0xFF; - } - return 0; -} - -bool ducky_get_number(const char* param, uint32_t* val) { - uint32_t value = 0; - if(strint_to_uint32(param, NULL, &value, 10) == StrintParseNoError) { - *val = value; - return true; - } - return false; -} - -void ducky_numlock_on(BadBleScript* bad_ble) { - if((bad_ble->hid->get_led_state(bad_ble->hid_inst) & HID_KB_LED_NUM) == 0) { - bad_ble->hid->kb_press(bad_ble->hid_inst, HID_KEYBOARD_LOCK_NUM_LOCK); - bad_ble->hid->kb_release(bad_ble->hid_inst, HID_KEYBOARD_LOCK_NUM_LOCK); - } -} - -bool ducky_numpad_press(BadBleScript* bad_ble, const char num) { - if((num < '0') || (num > '9')) return false; - - uint16_t key = numpad_keys[num - '0']; - bad_ble->hid->kb_press(bad_ble->hid_inst, key); - bad_ble->hid->kb_release(bad_ble->hid_inst, key); - - return true; -} - -bool ducky_altchar(BadBleScript* bad_ble, const char* charcode) { - uint8_t i = 0; - bool state = false; - - bad_ble->hid->kb_press(bad_ble->hid_inst, KEY_MOD_LEFT_ALT); - - while(!ducky_is_line_end(charcode[i])) { - state = ducky_numpad_press(bad_ble, charcode[i]); - if(state == false) break; - i++; - } - - bad_ble->hid->kb_release(bad_ble->hid_inst, KEY_MOD_LEFT_ALT); - return state; -} - -bool ducky_altstring(BadBleScript* bad_ble, 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 - } - - char temp_str[4]; - snprintf(temp_str, 4, "%u", param[i]); - - state = ducky_altchar(bad_ble, temp_str); - if(state == false) break; - i++; - } - return state; -} - -int32_t ducky_error(BadBleScript* bad_ble, const char* text, ...) { - va_list args; - va_start(args, text); - - vsnprintf(bad_ble->st.error, sizeof(bad_ble->st.error), text, args); - - va_end(args); - return SCRIPT_STATE_ERROR; -} - -bool ducky_string(BadBleScript* bad_ble, const char* param) { - uint32_t i = 0; - - while(param[i] != '\0') { - if(param[i] != '\n') { - uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_ble, param[i]); - if(keycode != HID_KEYBOARD_NONE) { - bad_ble->hid->kb_press(bad_ble->hid_inst, keycode); - bad_ble->hid->kb_release(bad_ble->hid_inst, keycode); - } - } else { - bad_ble->hid->kb_press(bad_ble->hid_inst, HID_KEYBOARD_RETURN); - bad_ble->hid->kb_release(bad_ble->hid_inst, HID_KEYBOARD_RETURN); - } - i++; - } - bad_ble->stringdelay = 0; - return true; -} - -static bool ducky_string_next(BadBleScript* bad_ble) { - if(bad_ble->string_print_pos >= furi_string_size(bad_ble->string_print)) { - return true; - } - - char print_char = furi_string_get_char(bad_ble->string_print, bad_ble->string_print_pos); - - if(print_char != '\n') { - uint16_t keycode = BADUSB_ASCII_TO_KEY(bad_ble, print_char); - if(keycode != HID_KEYBOARD_NONE) { - bad_ble->hid->kb_press(bad_ble->hid_inst, keycode); - bad_ble->hid->kb_release(bad_ble->hid_inst, keycode); - } - } else { - bad_ble->hid->kb_press(bad_ble->hid_inst, HID_KEYBOARD_RETURN); - bad_ble->hid->kb_release(bad_ble->hid_inst, HID_KEYBOARD_RETURN); - } - - bad_ble->string_print_pos++; - - return false; -} - -static int32_t ducky_parse_line(BadBleScript* bad_ble, FuriString* line) { - uint32_t line_len = furi_string_size(line); - const char* line_tmp = furi_string_get_cstr(line); - - if(line_len == 0) { - return SCRIPT_STATE_NEXT_LINE; // Skip empty lines - } - FURI_LOG_D(WORKER_TAG, "line:%s", line_tmp); - - // Ducky Lang Functions - int32_t cmd_result = ducky_execute_cmd(bad_ble, line_tmp); - if(cmd_result != SCRIPT_STATE_CMD_UNKNOWN) { - return cmd_result; - } - - // Special keys + modifiers - uint16_t key = ducky_get_keycode(bad_ble, line_tmp, false); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_ble, "No keycode defined for %s", line_tmp); - } - if((key & 0xFF00) != 0) { - // It's a modifier key - line_tmp = &line_tmp[ducky_get_command_len(line_tmp) + 1]; - key |= ducky_get_keycode(bad_ble, line_tmp, true); - } - bad_ble->hid->kb_press(bad_ble->hid_inst, key); - bad_ble->hid->kb_release(bad_ble->hid_inst, key); - return 0; -} - -static bool ducky_set_usb_id(BadBleScript* bad_ble, const char* line) { - if(sscanf(line, "%lX:%lX", &bad_ble->hid_cfg.vid, &bad_ble->hid_cfg.pid) == 2) { - bad_ble->hid_cfg.manuf[0] = '\0'; - bad_ble->hid_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_ble->hid_cfg.manuf, - bad_ble->hid_cfg.product); - } - FURI_LOG_D( - WORKER_TAG, - "set id: %04lX:%04lX mfr:%s product:%s", - bad_ble->hid_cfg.vid, - bad_ble->hid_cfg.pid, - bad_ble->hid_cfg.manuf, - bad_ble->hid_cfg.product); - return true; - } - return false; -} - -static void bad_ble_hid_state_callback(bool state, void* context) { - furi_assert(context); - BadBleScript* bad_ble = context; - - if(state == true) { - furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtConnect); - } else { - furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtDisconnect); - } -} - -static bool ducky_script_preload(BadBleScript* bad_ble, File* script_file) { - uint8_t ret = 0; - uint32_t line_len = 0; - - furi_string_reset(bad_ble->line); - - do { - ret = storage_file_read(script_file, bad_ble->file_buf, FILE_BUFFER_LEN); - for(uint16_t i = 0; i < ret; i++) { - if(bad_ble->file_buf[i] == '\n' && line_len > 0) { - bad_ble->st.line_nb++; - line_len = 0; - } else { - if(bad_ble->st.line_nb == 0) { // Save first line - furi_string_push_back(bad_ble->line, bad_ble->file_buf[i]); - } - line_len++; - } - } - if(storage_file_eof(script_file)) { - if(line_len > 0) { - bad_ble->st.line_nb++; - break; - } - } - } while(ret > 0); - - const char* line_tmp = furi_string_get_cstr(bad_ble->line); - bool id_set = false; // Looking for ID command at first line - if(strncmp(line_tmp, ducky_cmd_id, strlen(ducky_cmd_id)) == 0) { - id_set = ducky_set_usb_id(bad_ble, &line_tmp[strlen(ducky_cmd_id) + 1]); - } - - if(id_set) { - bad_ble->hid_inst = bad_ble->hid->init(&bad_ble->hid_cfg); - } else { - bad_ble->hid_inst = bad_ble->hid->init(NULL); - } - bad_ble->hid->set_state_callback(bad_ble->hid_inst, bad_ble_hid_state_callback, bad_ble); - - storage_file_seek(script_file, 0, true); - furi_string_reset(bad_ble->line); - - return true; -} - -static int32_t ducky_script_execute_next(BadBleScript* bad_ble, File* script_file) { - int32_t delay_val = 0; - - if(bad_ble->repeat_cnt > 0) { - bad_ble->repeat_cnt--; - delay_val = ducky_parse_line(bad_ble, bad_ble->line_prev); - if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line - return 0; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays - return delay_val; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button - return delay_val; - } else if(delay_val < 0) { // Script error - bad_ble->st.error_line = bad_ble->st.line_cur - 1; - FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_ble->st.line_cur - 1U); - return SCRIPT_STATE_ERROR; - } else { - return delay_val + bad_ble->defdelay; - } - } - - furi_string_set(bad_ble->line_prev, bad_ble->line); - furi_string_reset(bad_ble->line); - - while(1) { - if(bad_ble->buf_len == 0) { - bad_ble->buf_len = storage_file_read(script_file, bad_ble->file_buf, FILE_BUFFER_LEN); - if(storage_file_eof(script_file)) { - if((bad_ble->buf_len < FILE_BUFFER_LEN) && (bad_ble->file_end == false)) { - bad_ble->file_buf[bad_ble->buf_len] = '\n'; - bad_ble->buf_len++; - bad_ble->file_end = true; - } - } - - bad_ble->buf_start = 0; - if(bad_ble->buf_len == 0) return SCRIPT_STATE_END; - } - for(uint8_t i = bad_ble->buf_start; i < (bad_ble->buf_start + bad_ble->buf_len); i++) { - if(bad_ble->file_buf[i] == '\n' && furi_string_size(bad_ble->line) > 0) { - bad_ble->st.line_cur++; - bad_ble->buf_len = bad_ble->buf_len + bad_ble->buf_start - (i + 1); - bad_ble->buf_start = i + 1; - furi_string_trim(bad_ble->line); - delay_val = ducky_parse_line(bad_ble, bad_ble->line); - if(delay_val == SCRIPT_STATE_NEXT_LINE) { // Empty line - return 0; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Print string with delays - return delay_val; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // wait for button - return delay_val; - } else if(delay_val < 0) { - bad_ble->st.error_line = bad_ble->st.line_cur; - FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_ble->st.line_cur); - return SCRIPT_STATE_ERROR; - } else { - return delay_val + bad_ble->defdelay; - } - } else { - furi_string_push_back(bad_ble->line, bad_ble->file_buf[i]); - } - } - bad_ble->buf_len = 0; - if(bad_ble->file_end) return SCRIPT_STATE_END; - } - - return 0; -} - -static uint32_t bad_ble_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 { - uint32_t state = furi_thread_flags_clear(flags); - furi_check((state & FuriFlagError) == 0); - } - return flags; -} - -static int32_t bad_ble_worker(void* context) { - BadBleScript* bad_ble = context; - - BadBleWorkerState worker_state = BadBleStateInit; - BadBleWorkerState pause_state = BadBleStateRunning; - int32_t delay_val = 0; - - FURI_LOG_I(WORKER_TAG, "Init"); - File* script_file = storage_file_alloc(furi_record_open(RECORD_STORAGE)); - bad_ble->line = furi_string_alloc(); - bad_ble->line_prev = furi_string_alloc(); - bad_ble->string_print = furi_string_alloc(); - - while(1) { - if(worker_state == BadBleStateInit) { // State: initialization - if(storage_file_open( - script_file, - furi_string_get_cstr(bad_ble->file_path), - FSAM_READ, - FSOM_OPEN_EXISTING)) { - if((ducky_script_preload(bad_ble, script_file)) && (bad_ble->st.line_nb > 0)) { - if(bad_ble->hid->is_connected(bad_ble->hid_inst)) { - worker_state = BadBleStateIdle; // Ready to run - } else { - worker_state = BadBleStateNotConnected; // USB not connected - } - } else { - worker_state = BadBleStateScriptError; // Script preload error - } - } else { - FURI_LOG_E(WORKER_TAG, "File open error"); - worker_state = BadBleStateFileError; // File open error - } - bad_ble->st.state = worker_state; - - } else if(worker_state == BadBleStateNotConnected) { // State: USB not connected - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtStartStop, - FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtConnect) { - worker_state = BadBleStateIdle; // Ready to run - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBleStateWillRun; // Will run when USB is connected - } - bad_ble->st.state = worker_state; - - } else if(worker_state == BadBleStateIdle) { // State: ready to start - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtDisconnect, FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { // Start executing script - dolphin_deed(DolphinDeedBadUsbPlayScript); - delay_val = 0; - bad_ble->buf_len = 0; - bad_ble->st.line_cur = 0; - bad_ble->defdelay = 0; - bad_ble->stringdelay = 0; - bad_ble->defstringdelay = 0; - bad_ble->repeat_cnt = 0; - bad_ble->key_hold_nb = 0; - bad_ble->file_end = false; - storage_file_seek(script_file, 0, true); - worker_state = BadBleStateRunning; - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBleStateNotConnected; // USB disconnected - } - bad_ble->st.state = worker_state; - - } else if(worker_state == BadBleStateWillRun) { // State: start on connection - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtConnect | WorkerEvtStartStop, FuriWaitForever); - - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtConnect) { // Start executing script - dolphin_deed(DolphinDeedBadUsbPlayScript); - delay_val = 0; - bad_ble->buf_len = 0; - bad_ble->st.line_cur = 0; - bad_ble->defdelay = 0; - bad_ble->stringdelay = 0; - bad_ble->defstringdelay = 0; - bad_ble->repeat_cnt = 0; - bad_ble->file_end = false; - storage_file_seek(script_file, 0, true); - // extra time for PC to recognize Flipper as keyboard - flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtDisconnect | WorkerEvtStartStop, - FuriFlagWaitAny | FuriFlagNoClear, - 1500); - if(flags == (unsigned)FuriFlagErrorTimeout) { - // If nothing happened - start script execution - worker_state = BadBleStateRunning; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBleStateIdle; - furi_thread_flags_clear(WorkerEvtStartStop); - } - } else if(flags & WorkerEvtStartStop) { // Cancel scheduled execution - worker_state = BadBleStateNotConnected; - } - bad_ble->st.state = worker_state; - - } else if(worker_state == BadBleStateRunning) { // State: running - uint16_t delay_cur = (delay_val > 1000) ? (1000) : (delay_val); - uint32_t flags = furi_thread_flags_wait( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect, - FuriFlagWaitAny, - delay_cur); - - delay_val -= delay_cur; - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBleStateIdle; // Stop executing script - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBleStateNotConnected; // USB disconnected - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtPauseResume) { - pause_state = BadBleStateRunning; - worker_state = BadBleStatePaused; // Pause - } - bad_ble->st.state = worker_state; - continue; - } else if( - (flags == (unsigned)FuriFlagErrorTimeout) || - (flags == (unsigned)FuriFlagErrorResource)) { - if(delay_val > 0) { - bad_ble->st.delay_remain--; - continue; - } - bad_ble->st.state = BadBleStateRunning; - delay_val = ducky_script_execute_next(bad_ble, script_file); - if(delay_val == SCRIPT_STATE_ERROR) { // Script error - delay_val = 0; - worker_state = BadBleStateScriptError; - bad_ble->st.state = worker_state; - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(delay_val == SCRIPT_STATE_END) { // End of script - delay_val = 0; - worker_state = BadBleStateIdle; - bad_ble->st.state = BadBleStateDone; - bad_ble->hid->release_all(bad_ble->hid_inst); - continue; - } else if(delay_val == SCRIPT_STATE_STRING_START) { // Start printing string with delays - delay_val = bad_ble->defdelay; - bad_ble->string_print_pos = 0; - worker_state = BadBleStateStringDelay; - } else if(delay_val == SCRIPT_STATE_WAIT_FOR_BTN) { // set state to wait for user input - worker_state = BadBleStateWaitForBtn; - bad_ble->st.state = BadBleStateWaitForBtn; // Show long delays - } else if(delay_val > 1000) { - bad_ble->st.state = BadBleStateDelay; // Show long delays - bad_ble->st.delay_remain = delay_val / 1000; - } - } else { - furi_check((flags & FuriFlagError) == 0); - } - } else if(worker_state == BadBleStateWaitForBtn) { // State: Wait for button Press - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect, - FuriWaitForever); - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - delay_val = 0; - worker_state = BadBleStateRunning; - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBleStateNotConnected; // USB disconnected - bad_ble->hid->release_all(bad_ble->hid_inst); - } - bad_ble->st.state = worker_state; - continue; - } - } else if(worker_state == BadBleStatePaused) { // State: Paused - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect, - FuriWaitForever); - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBleStateIdle; // Stop executing script - bad_ble->st.state = worker_state; - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBleStateNotConnected; // USB disconnected - bad_ble->st.state = worker_state; - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtPauseResume) { - if(pause_state == BadBleStateRunning) { - if(delay_val > 0) { - bad_ble->st.state = BadBleStateDelay; - bad_ble->st.delay_remain = delay_val / 1000; - } else { - bad_ble->st.state = BadBleStateRunning; - delay_val = 0; - } - worker_state = BadBleStateRunning; // Resume - } else if(pause_state == BadBleStateStringDelay) { - bad_ble->st.state = BadBleStateRunning; - worker_state = BadBleStateStringDelay; // Resume - } - } - continue; - } - } else if(worker_state == BadBleStateStringDelay) { // State: print string with delays - uint32_t delay = (bad_ble->stringdelay == 0) ? bad_ble->defstringdelay : - bad_ble->stringdelay; - uint32_t flags = bad_ble_flags_get( - WorkerEvtEnd | WorkerEvtStartStop | WorkerEvtPauseResume | WorkerEvtDisconnect, - delay); - - if(!(flags & FuriFlagError)) { - if(flags & WorkerEvtEnd) { - break; - } else if(flags & WorkerEvtStartStop) { - worker_state = BadBleStateIdle; // Stop executing script - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtDisconnect) { - worker_state = BadBleStateNotConnected; // USB disconnected - bad_ble->hid->release_all(bad_ble->hid_inst); - } else if(flags & WorkerEvtPauseResume) { - pause_state = BadBleStateStringDelay; - worker_state = BadBleStatePaused; // Pause - } - bad_ble->st.state = worker_state; - continue; - } else if( - (flags == (unsigned)FuriFlagErrorTimeout) || - (flags == (unsigned)FuriFlagErrorResource)) { - bool string_end = ducky_string_next(bad_ble); - if(string_end) { - bad_ble->stringdelay = 0; - worker_state = BadBleStateRunning; - } - } else { - furi_check((flags & FuriFlagError) == 0); - } - } else if( - (worker_state == BadBleStateFileError) || - (worker_state == BadBleStateScriptError)) { // State: error - uint32_t flags = - bad_ble_flags_get(WorkerEvtEnd, FuriWaitForever); // Waiting for exit command - - if(flags & WorkerEvtEnd) { - break; - } - } - } - - bad_ble->hid->set_state_callback(bad_ble->hid_inst, NULL, NULL); - bad_ble->hid->deinit(bad_ble->hid_inst); - - storage_file_close(script_file); - storage_file_free(script_file); - furi_string_free(bad_ble->line); - furi_string_free(bad_ble->line_prev); - furi_string_free(bad_ble->string_print); - - FURI_LOG_I(WORKER_TAG, "End"); - - 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))); -} - -BadBleScript* bad_ble_script_open(FuriString* file_path, BadBleHidInterface interface) { - 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); - - bad_ble->st.state = BadBleStateInit; - bad_ble->st.error[0] = '\0'; - bad_ble->hid = bad_ble_hid_get_interface(interface); - - 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_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); - - 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)) { //-V1051 - 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_start_stop(BadBleScript* bad_ble) { - furi_assert(bad_ble); - furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtStartStop); -} - -void bad_ble_script_pause_resume(BadBleScript* bad_ble) { - furi_assert(bad_ble); - furi_thread_flags_set(furi_thread_get_id(bad_ble->thread), WorkerEvtPauseResume); -} - -BadBleState* bad_ble_script_get_state(BadBleScript* bad_ble) { - furi_assert(bad_ble); - return &(bad_ble->st); -} diff --git a/applications/system/bad_ble/helpers/ducky_script.h b/applications/system/bad_ble/helpers/ducky_script.h deleted file mode 100644 index 044cae82561..00000000000 --- a/applications/system/bad_ble/helpers/ducky_script.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "bad_ble_hid.h" - -typedef enum { - BadBleStateInit, - BadBleStateNotConnected, - BadBleStateIdle, - BadBleStateWillRun, - BadBleStateRunning, - BadBleStateDelay, - BadBleStateStringDelay, - BadBleStateWaitForBtn, - BadBleStatePaused, - BadBleStateDone, - BadBleStateScriptError, - BadBleStateFileError, -} BadBleWorkerState; - -typedef struct { - BadBleWorkerState state; - size_t line_cur; - size_t line_nb; - uint32_t delay_remain; - size_t error_line; - char error[64]; -} BadBleState; - -typedef struct BadBleScript BadBleScript; - -BadBleScript* bad_ble_script_open(FuriString* file_path, BadBleHidInterface interface); - -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_start_stop(BadBleScript* bad_ble); - -void bad_ble_script_pause_resume(BadBleScript* bad_ble); - -BadBleState* bad_ble_script_get_state(BadBleScript* bad_ble); - -#ifdef __cplusplus -} -#endif diff --git a/applications/system/bad_ble/helpers/ducky_script_commands.c b/applications/system/bad_ble/helpers/ducky_script_commands.c deleted file mode 100644 index f70c5eba400..00000000000 --- a/applications/system/bad_ble/helpers/ducky_script_commands.c +++ /dev/null @@ -1,241 +0,0 @@ -#include -#include "ducky_script.h" -#include "ducky_script_i.h" - -typedef int32_t (*DuckyCmdCallback)(BadBleScript* bad_usb, const char* line, int32_t param); - -typedef struct { - char* name; - DuckyCmdCallback callback; - int32_t param; -} DuckyCmd; - -static int32_t ducky_fnc_delay(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint32_t delay_val = 0; - bool state = ducky_get_number(line, &delay_val); - if((state) && (delay_val > 0)) { - return (int32_t)delay_val; - } - - return ducky_error(bad_usb, "Invalid number %s", line); -} - -static int32_t ducky_fnc_defdelay(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_usb->defdelay); - if(!state) { - return ducky_error(bad_usb, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_strdelay(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_usb->stringdelay); - if(!state) { - return ducky_error(bad_usb, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_defstrdelay(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_usb->defstringdelay); - if(!state) { - return ducky_error(bad_usb, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_string(BadBleScript* bad_usb, const char* line, int32_t param) { - line = &line[ducky_get_command_len(line) + 1]; - furi_string_set_str(bad_usb->string_print, line); - if(param == 1) { - furi_string_cat(bad_usb->string_print, "\n"); - } - - if(bad_usb->stringdelay == 0 && - bad_usb->defstringdelay == 0) { // stringdelay not set - run command immediately - bool state = ducky_string(bad_usb, furi_string_get_cstr(bad_usb->string_print)); - if(!state) { - return ducky_error(bad_usb, "Invalid string %s", line); - } - } else { // stringdelay is set - run command in thread to keep handling external events - return SCRIPT_STATE_STRING_START; - } - - return 0; -} - -static int32_t ducky_fnc_repeat(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - bool state = ducky_get_number(line, &bad_usb->repeat_cnt); - if((!state) || (bad_usb->repeat_cnt == 0)) { - return ducky_error(bad_usb, "Invalid number %s", line); - } - return 0; -} - -static int32_t ducky_fnc_sysrq(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_usb, line, true); - bad_usb->hid->kb_press(bad_usb->hid_inst, KEY_MOD_LEFT_ALT | HID_KEYBOARD_PRINT_SCREEN); - bad_usb->hid->kb_press(bad_usb->hid_inst, key); - bad_usb->hid->release_all(bad_usb->hid_inst); - return 0; -} - -static int32_t ducky_fnc_altchar(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - ducky_numlock_on(bad_usb); - bool state = ducky_altchar(bad_usb, line); - if(!state) { - return ducky_error(bad_usb, "Invalid altchar %s", line); - } - return 0; -} - -static int32_t ducky_fnc_altstring(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - ducky_numlock_on(bad_usb); - bool state = ducky_altstring(bad_usb, line); - if(!state) { - return ducky_error(bad_usb, "Invalid altstring %s", line); - } - return 0; -} - -static int32_t ducky_fnc_hold(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_usb, line, true); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_usb, "No keycode defined for %s", line); - } - bad_usb->key_hold_nb++; - if(bad_usb->key_hold_nb > (HID_KB_MAX_KEYS - 1)) { - return ducky_error(bad_usb, "Too many keys are hold"); - } - bad_usb->hid->kb_press(bad_usb->hid_inst, key); - return 0; -} - -static int32_t ducky_fnc_release(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_usb, line, true); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_usb, "No keycode defined for %s", line); - } - if(bad_usb->key_hold_nb == 0) { - return ducky_error(bad_usb, "No keys are hold"); - } - bad_usb->key_hold_nb--; - bad_usb->hid->kb_release(bad_usb->hid_inst, key); - return 0; -} - -static int32_t ducky_fnc_media(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_media_keycode_by_name(line); - if(key == HID_CONSUMER_UNASSIGNED) { - return ducky_error(bad_usb, "No keycode defined for %s", line); - } - bad_usb->hid->consumer_press(bad_usb->hid_inst, key); - bad_usb->hid->consumer_release(bad_usb->hid_inst, key); - return 0; -} - -static int32_t ducky_fnc_globe(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - - line = &line[ducky_get_command_len(line) + 1]; - uint16_t key = ducky_get_keycode(bad_usb, line, true); - if(key == HID_KEYBOARD_NONE) { - return ducky_error(bad_usb, "No keycode defined for %s", line); - } - - bad_usb->hid->consumer_press(bad_usb->hid_inst, HID_CONSUMER_FN_GLOBE); - bad_usb->hid->kb_press(bad_usb->hid_inst, key); - bad_usb->hid->kb_release(bad_usb->hid_inst, key); - bad_usb->hid->consumer_release(bad_usb->hid_inst, HID_CONSUMER_FN_GLOBE); - return 0; -} - -static int32_t ducky_fnc_waitforbutton(BadBleScript* bad_usb, const char* line, int32_t param) { - UNUSED(param); - UNUSED(bad_usb); - UNUSED(line); - - return SCRIPT_STATE_WAIT_FOR_BTN; -} - -static const DuckyCmd ducky_commands[] = { - {"REM", NULL, -1}, - {"ID", NULL, -1}, - {"DELAY", ducky_fnc_delay, -1}, - {"STRING", ducky_fnc_string, 0}, - {"STRINGLN", ducky_fnc_string, 1}, - {"DEFAULT_DELAY", ducky_fnc_defdelay, -1}, - {"DEFAULTDELAY", ducky_fnc_defdelay, -1}, - {"STRINGDELAY", ducky_fnc_strdelay, -1}, - {"STRING_DELAY", ducky_fnc_strdelay, -1}, - {"DEFAULT_STRING_DELAY", ducky_fnc_defstrdelay, -1}, - {"DEFAULTSTRINGDELAY", ducky_fnc_defstrdelay, -1}, - {"REPEAT", ducky_fnc_repeat, -1}, - {"SYSRQ", ducky_fnc_sysrq, -1}, - {"ALTCHAR", ducky_fnc_altchar, -1}, - {"ALTSTRING", ducky_fnc_altstring, -1}, - {"ALTCODE", ducky_fnc_altstring, -1}, - {"HOLD", ducky_fnc_hold, -1}, - {"RELEASE", ducky_fnc_release, -1}, - {"WAIT_FOR_BUTTON_PRESS", ducky_fnc_waitforbutton, -1}, - {"MEDIA", ducky_fnc_media, -1}, - {"GLOBE", ducky_fnc_globe, -1}, -}; - -#define TAG "BadBle" - -#define WORKER_TAG TAG "Worker" - -int32_t ducky_execute_cmd(BadBleScript* bad_usb, const char* line) { - size_t cmd_word_len = strcspn(line, " "); - for(size_t i = 0; i < COUNT_OF(ducky_commands); i++) { - size_t cmd_compare_len = strlen(ducky_commands[i].name); - - if(cmd_compare_len != cmd_word_len) { - continue; - } - - if(strncmp(line, ducky_commands[i].name, cmd_compare_len) == 0) { - if(ducky_commands[i].callback == NULL) { - return 0; - } else { - return (ducky_commands[i].callback)(bad_usb, line, ducky_commands[i].param); - } - } - } - - return SCRIPT_STATE_CMD_UNKNOWN; -} diff --git a/applications/system/bad_ble/helpers/ducky_script_i.h b/applications/system/bad_ble/helpers/ducky_script_i.h deleted file mode 100644 index a5581d20655..00000000000 --- a/applications/system/bad_ble/helpers/ducky_script_i.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "ducky_script.h" -#include "bad_ble_hid.h" - -#define SCRIPT_STATE_ERROR (-1) -#define SCRIPT_STATE_END (-2) -#define SCRIPT_STATE_NEXT_LINE (-3) -#define SCRIPT_STATE_CMD_UNKNOWN (-4) -#define SCRIPT_STATE_STRING_START (-5) -#define SCRIPT_STATE_WAIT_FOR_BTN (-6) - -#define FILE_BUFFER_LEN 16 - -struct BadBleScript { - FuriHalUsbHidConfig hid_cfg; - const BadBleHidApi* hid; - void* hid_inst; - FuriThread* thread; - BadBleState st; - - FuriString* file_path; - uint8_t file_buf[FILE_BUFFER_LEN + 1]; - uint8_t buf_start; - uint8_t buf_len; - bool file_end; - - uint32_t defdelay; - uint32_t stringdelay; - uint32_t defstringdelay; - uint16_t layout[128]; - - FuriString* line; - FuriString* line_prev; - uint32_t repeat_cnt; - uint8_t key_hold_nb; - - FuriString* string_print; - size_t string_print_pos; -}; - -uint16_t ducky_get_keycode(BadBleScript* bad_usb, const char* param, bool accept_chars); - -uint32_t ducky_get_command_len(const char* line); - -bool ducky_is_line_end(const char chr); - -uint16_t ducky_get_keycode_by_name(const char* param); - -uint16_t ducky_get_media_keycode_by_name(const char* param); - -bool ducky_get_number(const char* param, uint32_t* val); - -void ducky_numlock_on(BadBleScript* bad_usb); - -bool ducky_numpad_press(BadBleScript* bad_usb, const char num); - -bool ducky_altchar(BadBleScript* bad_usb, const char* charcode); - -bool ducky_altstring(BadBleScript* bad_usb, const char* param); - -bool ducky_string(BadBleScript* bad_usb, const char* param); - -int32_t ducky_execute_cmd(BadBleScript* bad_usb, const char* line); - -int32_t ducky_error(BadBleScript* bad_usb, const char* text, ...); - -#ifdef __cplusplus -} -#endif diff --git a/applications/system/bad_ble/helpers/ducky_script_keycodes.c b/applications/system/bad_ble/helpers/ducky_script_keycodes.c deleted file mode 100644 index 290618c131b..00000000000 --- a/applications/system/bad_ble/helpers/ducky_script_keycodes.c +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include "ducky_script_i.h" - -typedef struct { - char* name; - uint16_t keycode; -} DuckyKey; - -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}, - {"GUI-CTRL", KEY_MOD_LEFT_GUI | KEY_MOD_LEFT_CTRL}, - - {"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}, - - {"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}, - - {"ENTER", HID_KEYBOARD_RETURN}, - {"BREAK", HID_KEYBOARD_PAUSE}, - {"PAUSE", HID_KEYBOARD_PAUSE}, - {"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK}, - {"DELETE", HID_KEYBOARD_DELETE_FORWARD}, - {"BACKSPACE", HID_KEYBOARD_DELETE}, - {"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}, - - {"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}, - {"F13", HID_KEYBOARD_F13}, - {"F14", HID_KEYBOARD_F14}, - {"F15", HID_KEYBOARD_F15}, - {"F16", HID_KEYBOARD_F16}, - {"F17", HID_KEYBOARD_F17}, - {"F18", HID_KEYBOARD_F18}, - {"F19", HID_KEYBOARD_F19}, - {"F20", HID_KEYBOARD_F20}, - {"F21", HID_KEYBOARD_F21}, - {"F22", HID_KEYBOARD_F22}, - {"F23", HID_KEYBOARD_F23}, - {"F24", HID_KEYBOARD_F24}, -}; - -static const DuckyKey ducky_media_keys[] = { - {"POWER", HID_CONSUMER_POWER}, - {"REBOOT", HID_CONSUMER_RESET}, - {"SLEEP", HID_CONSUMER_SLEEP}, - {"LOGOFF", HID_CONSUMER_AL_LOGOFF}, - - {"EXIT", HID_CONSUMER_AC_EXIT}, - {"HOME", HID_CONSUMER_AC_HOME}, - {"BACK", HID_CONSUMER_AC_BACK}, - {"FORWARD", HID_CONSUMER_AC_FORWARD}, - {"REFRESH", HID_CONSUMER_AC_REFRESH}, - - {"SNAPSHOT", HID_CONSUMER_SNAPSHOT}, - - {"PLAY", HID_CONSUMER_PLAY}, - {"PAUSE", HID_CONSUMER_PAUSE}, - {"PLAY_PAUSE", HID_CONSUMER_PLAY_PAUSE}, - {"NEXT_TRACK", HID_CONSUMER_SCAN_NEXT_TRACK}, - {"PREV_TRACK", HID_CONSUMER_SCAN_PREVIOUS_TRACK}, - {"STOP", HID_CONSUMER_STOP}, - {"EJECT", HID_CONSUMER_EJECT}, - - {"MUTE", HID_CONSUMER_MUTE}, - {"VOLUME_UP", HID_CONSUMER_VOLUME_INCREMENT}, - {"VOLUME_DOWN", HID_CONSUMER_VOLUME_DECREMENT}, - - {"FN", HID_CONSUMER_FN_GLOBE}, - {"BRIGHT_UP", HID_CONSUMER_BRIGHTNESS_INCREMENT}, - {"BRIGHT_DOWN", HID_CONSUMER_BRIGHTNESS_DECREMENT}, -}; - -uint16_t ducky_get_keycode_by_name(const char* param) { - for(size_t i = 0; i < COUNT_OF(ducky_keys); i++) { - size_t key_cmd_len = strlen(ducky_keys[i].name); - if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && - (ducky_is_line_end(param[key_cmd_len]))) { - return ducky_keys[i].keycode; - } - } - - return HID_KEYBOARD_NONE; -} - -uint16_t ducky_get_media_keycode_by_name(const char* param) { - for(size_t i = 0; i < COUNT_OF(ducky_media_keys); i++) { - size_t key_cmd_len = strlen(ducky_media_keys[i].name); - if((strncmp(param, ducky_media_keys[i].name, key_cmd_len) == 0) && - (ducky_is_line_end(param[key_cmd_len]))) { - return ducky_media_keys[i].keycode; - } - } - - return HID_CONSUMER_UNASSIGNED; -} diff --git a/applications/system/bad_ble/icon.png b/applications/system/bad_ble/icon.png deleted file mode 100644 index 27355f8dbab..00000000000 Binary files a/applications/system/bad_ble/icon.png and /dev/null differ diff --git a/applications/system/bad_ble/scenes/bad_ble_scene.c b/applications/system/bad_ble/scenes/bad_ble_scene.c deleted file mode 100644 index 351bb1e7945..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene.c +++ /dev/null @@ -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, -}; diff --git a/applications/system/bad_ble/scenes/bad_ble_scene.h b/applications/system/bad_ble/scenes/bad_ble_scene.h deleted file mode 100644 index 25b19fc4b55..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -// 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 diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_config.c b/applications/system/bad_ble/scenes/bad_ble_scene_config.c deleted file mode 100644 index 1f64f19039d..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_config.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../bad_ble_app_i.h" - -enum SubmenuIndex { - ConfigIndexKeyboardLayout, - ConfigIndexBleUnpair, -}; - -void bad_ble_scene_config_select_callback(void* context, uint32_t index) { - BadBleApp* bad_ble = context; - - view_dispatcher_send_custom_event(bad_ble->view_dispatcher, index); -} - -static void draw_menu(BadBleApp* bad_ble) { - VariableItemList* var_item_list = bad_ble->var_item_list; - - variable_item_list_reset(var_item_list); - - variable_item_list_add(var_item_list, "Keyboard Layout (Global)", 0, NULL, NULL); - - variable_item_list_add(var_item_list, "Unpair Device", 0, NULL, NULL); -} - -void bad_ble_scene_config_on_enter(void* context) { - BadBleApp* bad_ble = context; - VariableItemList* var_item_list = bad_ble->var_item_list; - - variable_item_list_set_enter_callback( - var_item_list, bad_ble_scene_config_select_callback, bad_ble); - draw_menu(bad_ble); - variable_item_list_set_selected_item(var_item_list, 0); - - 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) { - consumed = true; - if(event.event == ConfigIndexKeyboardLayout) { - scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneConfigLayout); - } else if(event.event == ConfigIndexBleUnpair) { - scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneConfirmUnpair); - } else { - furi_crash("Unknown key type"); - } - } - - return consumed; -} - -void bad_ble_scene_config_on_exit(void* context) { - BadBleApp* bad_ble = context; - VariableItemList* var_item_list = bad_ble->var_item_list; - - variable_item_list_reset(var_item_list); -} diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_config.h b/applications/system/bad_ble/scenes/bad_ble_scene_config.h deleted file mode 100644 index 5675fca59b7..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_config.h +++ /dev/null @@ -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, confirm_unpair, ConfirmUnpair) -ADD_SCENE(bad_ble, unpair_done, UnpairDone) diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_config_layout.c b/applications/system/bad_ble/scenes/bad_ble_scene_config_layout.c deleted file mode 100644 index 594525dd7b7..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_config_layout.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "../bad_ble_app_i.h" -#include - -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); - browser_options.base_path = BAD_BLE_APP_PATH_LAYOUT_FOLDER; - browser_options.skip_assets = false; - - // 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)) { - scene_manager_search_and_switch_to_previous_scene(bad_ble->scene_manager, BadBleSceneWork); - } else { - 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; -} diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_error.c b/applications/system/bad_ble/scenes/bad_ble_scene_error.c deleted file mode 100644 index c9c2b12da2b..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_error.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "../bad_ble_app_i.h" - -typedef enum { - BadBleCustomEventErrorBack, -} BadBleCustomEvent; - -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; - - 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, BadBleAppViewWidget); -} - -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); -} diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_file_select.c b/applications/system/bad_ble/scenes/bad_ble_scene_file_select.c deleted file mode 100644 index 2a182a874d2..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_file_select.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "../bad_ble_app_i.h" -#include -#include - -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; - - 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)) { - scene_manager_next_scene(bad_ble->scene_manager, BadBleSceneWork); - } else { - 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; -} diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_unpair_done.c b/applications/system/bad_ble/scenes/bad_ble_scene_unpair_done.c deleted file mode 100644 index 4c1fe3366b1..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_unpair_done.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../bad_ble_app_i.h" - -static void bad_ble_scene_unpair_done_popup_callback(void* context) { - BadBleApp* bad_ble = context; - scene_manager_search_and_switch_to_previous_scene(bad_ble->scene_manager, BadBleSceneConfig); -} - -void bad_ble_scene_unpair_done_on_enter(void* context) { - BadBleApp* bad_ble = context; - Popup* popup = bad_ble->popup; - - popup_set_icon(popup, 48, 4, &I_DolphinDone_80x58); - popup_set_header(popup, "Done", 20, 19, AlignLeft, AlignBottom); - popup_set_callback(popup, bad_ble_scene_unpair_done_popup_callback); - popup_set_context(popup, bad_ble); - popup_set_timeout(popup, 1000); - popup_enable_timeout(popup); - - view_dispatcher_switch_to_view(bad_ble->view_dispatcher, BadBleAppViewPopup); -} - -bool bad_ble_scene_unpair_done_on_event(void* context, SceneManagerEvent event) { - BadBleApp* bad_ble = context; - UNUSED(bad_ble); - UNUSED(event); - - bool consumed = false; - - return consumed; -} - -void bad_ble_scene_unpair_done_on_exit(void* context) { - BadBleApp* bad_ble = context; - Popup* popup = bad_ble->popup; - - popup_reset(popup); -} diff --git a/applications/system/bad_ble/scenes/bad_ble_scene_work.c b/applications/system/bad_ble/scenes/bad_ble_scene_work.c deleted file mode 100644 index ff71edc3c21..00000000000 --- a/applications/system/bad_ble/scenes/bad_ble_scene_work.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "../helpers/ducky_script.h" -#include "../bad_ble_app_i.h" -#include "../views/bad_ble_view.h" -#include -#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) { - if(bad_ble_view_is_idle_state(app->bad_ble_view)) { - bad_ble_script_close(app->bad_ble_script); - app->bad_ble_script = NULL; - - scene_manager_next_scene(app->scene_manager, BadBleSceneConfig); - } - consumed = true; - } else if(event.event == InputKeyOk) { - bad_ble_script_start_stop(app->bad_ble_script); - consumed = true; - } else if(event.event == InputKeyRight) { - bad_ble_script_pause_resume(app->bad_ble_script); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - bad_ble_view_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; - - app->bad_ble_script = bad_ble_script_open(app->file_path, app->interface); - bad_ble_script_set_keyboard_layout(app->bad_ble_script, app->keyboard_layout); - - FuriString* file_name; - file_name = furi_string_alloc(); - path_extract_filename(app->file_path, file_name, true); - bad_ble_view_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_view_set_layout(app->bad_ble_view, furi_string_get_cstr(layout)); - furi_string_free(layout); - - bad_ble_view_set_state(app->bad_ble_view, bad_ble_script_get_state(app->bad_ble_script)); - - bad_ble_view_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); -} diff --git a/applications/system/bad_ble/views/bad_ble_view.c b/applications/system/bad_ble/views/bad_ble_view.c deleted file mode 100644 index 28f935733ef..00000000000 --- a/applications/system/bad_ble/views/bad_ble_view.c +++ /dev/null @@ -1,284 +0,0 @@ -#include "bad_ble_view.h" -#include "../helpers/ducky_script.h" -#include -#include -#include -#include "bad_ble_icons.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; - bool pause_wait; - 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)); - - if(strlen(model->layout) == 0) { - furi_string_set(disp_str, "(default)"); - } else { - furi_string_printf(disp_str, "(%s)", model->layout); - } - 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_Bad_BLE_48x22); - - BadBleWorkerState state = model->state.state; - - if((state == BadBleStateIdle) || (state == BadBleStateDone) || - (state == BadBleStateNotConnected)) { - elements_button_center(canvas, "Run"); - elements_button_left(canvas, "Config"); - } else if((state == BadBleStateRunning) || (state == BadBleStateDelay)) { - elements_button_center(canvas, "Stop"); - if(!model->pause_wait) { - elements_button_right(canvas, "Pause"); - } - } else if(state == BadBleStatePaused) { - elements_button_center(canvas, "End"); - elements_button_right(canvas, "Resume"); - } else if(state == BadBleStateWaitForBtn) { - elements_button_center(canvas, "Press to continue"); - } else if(state == BadBleStateWillRun) { - elements_button_center(canvas, "Cancel"); - } - - if(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"); - canvas_draw_str_aligned(canvas, 127, 43, AlignRight, AlignBottom, "to device"); - } else if(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(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(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 %zu", model->state.error_line); - canvas_draw_str_aligned( - canvas, 127, 46, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - - furi_string_set_str(disp_str, model->state.error); - elements_string_fit_width(canvas, disp_str, canvas_width(canvas)); - canvas_draw_str_aligned( - canvas, 127, 56, AlignRight, AlignBottom, furi_string_get_cstr(disp_str)); - furi_string_reset(disp_str); - } else if(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(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, "%zu", ((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(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(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, "%zu", ((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 if((state == BadBleStatePaused) || (state == BadBleStateWaitForBtn)) { - 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, "%zu", ((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); - canvas_draw_str_aligned(canvas, 127, 50, AlignRight, AlignBottom, "Paused"); - furi_string_reset(disp_str); - } else { - canvas_draw_icon(canvas, 4, 26, &I_Clock_18x18); - } - - furi_string_free(disp_str); -} - -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) { - consumed = true; - furi_assert(bad_ble->callback); - bad_ble->callback(event->key, bad_ble->context); - } else if(event->key == InputKeyOk) { - with_view_model( - bad_ble->view, BadBleModel * model, { model->pause_wait = false; }, true); - consumed = true; - furi_assert(bad_ble->callback); - bad_ble->callback(event->key, bad_ble->context); - } else if(event->key == InputKeyRight) { - with_view_model( - bad_ble->view, - BadBleModel * model, - { - if((model->state.state == BadBleStateRunning) || - (model->state.state == BadBleStateDelay)) { - model->pause_wait = true; - } - }, - true); - consumed = true; - furi_assert(bad_ble->callback); - bad_ble->callback(event->key, bad_ble->context); - } - } - - return consumed; -} - -BadBle* bad_ble_view_alloc(void) { - 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_view_free(BadBle* bad_ble) { - furi_assert(bad_ble); - view_free(bad_ble->view); - free(bad_ble); -} - -View* bad_ble_view_get_view(BadBle* bad_ble) { - furi_assert(bad_ble); - return bad_ble->view; -} - -void bad_ble_view_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_view_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_view_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_view_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; - if(model->state.state == BadBleStatePaused) { - model->pause_wait = false; - } - }, - true); -} - -bool bad_ble_view_is_idle_state(BadBle* bad_ble) { - bool is_idle = false; - with_view_model( - bad_ble->view, - BadBleModel * model, - { - if((model->state.state == BadBleStateIdle) || - (model->state.state == BadBleStateDone) || - (model->state.state == BadBleStateNotConnected)) { - is_idle = true; - } - }, - false); - return is_idle; -} diff --git a/applications/system/bad_ble/views/bad_ble_view.h b/applications/system/bad_ble/views/bad_ble_view.h deleted file mode 100644 index e26488818e4..00000000000 --- a/applications/system/bad_ble/views/bad_ble_view.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include "../helpers/ducky_script.h" - -typedef struct BadBle BadBle; -typedef void (*BadBleButtonCallback)(InputKey key, void* context); - -BadBle* bad_ble_view_alloc(void); - -void bad_ble_view_free(BadBle* bad_ble); - -View* bad_ble_view_get_view(BadBle* bad_ble); - -void bad_ble_view_set_button_callback( - BadBle* bad_ble, - BadBleButtonCallback callback, - void* context); - -void bad_ble_view_set_file_name(BadBle* bad_ble, const char* name); - -void bad_ble_view_set_layout(BadBle* bad_ble, const char* layout); - -void bad_ble_view_set_state(BadBle* bad_ble, BadBleState* st); - -bool bad_ble_view_is_idle_state(BadBle* bad_ble); diff --git a/applications/system/bad_ble/assets/Bad_BLE_48x22.png b/assets/icons/BadUsb/Bad_BLE_48x22.png similarity index 100% rename from applications/system/bad_ble/assets/Bad_BLE_48x22.png rename to assets/icons/BadUsb/Bad_BLE_48x22.png diff --git a/furi/core/timer.c b/furi/core/timer.c index ddd82e33194..fe3f3db17fa 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -119,8 +119,6 @@ FuriStatus furi_timer_stop(FuriTimer* instance) { furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS); - furi_timer_flush(); - return FuriStatusOk; }