From 03140e434916e206ac3553e0d1e5dca71f0038cb Mon Sep 17 00:00:00 2001 From: Smooklu <37220586+Smooklu@users.noreply.github.com> Date: Mon, 28 Nov 2022 10:27:16 -0600 Subject: [PATCH] Bluetooth Remote to HID Remote (#2039) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP BT + USB Hid * Refactoring Submenus/Views * Changed to bool instead of enum * Revamp finished * Removed usb_keyboard * Renaming device_types that can do USB+BT * Removed error view * Renaming folder structure and file names * Fixed views.h * Fixed hid.h * Fixed hid_mouse.c * Fixed a accidetnal renaming * Apps: add missing view remove call in hid app destructor * Hid app: hal abstraction, split into bluetooth and usb remotes. Fbt: customizable icon symbol name. * Hid app: update usb remote icon * Hid: single status change routine * HID App: final touches * HID App: rename BtHidTikTok to HidTikTok, format sources * HID App: fix comma in keyboard Co-authored-by: あく --- .../plugins/bt_hid_app/application.fam | 10 - applications/plugins/bt_hid_app/bt_hid.c | 216 ----------- applications/plugins/bt_hid_app/bt_hid.h | 41 -- .../bt_hid_app/views/bt_hid_keyboard.h | 13 - .../plugins/bt_hid_app/views/bt_hid_keynote.h | 13 - .../plugins/bt_hid_app/views/bt_hid_media.h | 13 - .../plugins/bt_hid_app/views/bt_hid_mouse.h | 13 - .../plugins/bt_hid_app/views/bt_hid_tiktok.h | 13 - applications/plugins/hid_app/application.fam | 24 ++ .../assets/Arr_dwn_7x9.png | Bin .../assets/Arr_up_7x9.png | Bin .../assets/Ble_connected_15x15.png | Bin .../assets/Ble_disconnected_15x15.png | Bin .../assets/ButtonDown_7x4.png | Bin .../assets/ButtonLeft_4x7.png | Bin .../assets/ButtonRight_4x7.png | Bin .../assets/ButtonUp_7x4.png | Bin .../assets/Button_18x18.png | Bin .../assets/Circles_47x47.png | Bin .../assets/Left_mouse_icon_9x9.png | Bin .../assets/Like_def_11x9.png | Bin .../assets/Like_pressed_17x17.png | Bin .../assets/Ok_btn_9x9.png | Bin .../assets/Ok_btn_pressed_13x13.png | Bin .../assets/Pin_arrow_down_7x9.png | Bin .../assets/Pin_arrow_left_9x7.png | Bin .../assets/Pin_arrow_right_9x7.png | Bin .../assets/Pin_arrow_up_7x9.png | Bin .../assets/Pin_back_arrow_10x8.png | Bin .../assets/Pressed_Button_13x13.png | Bin .../assets/Right_mouse_icon_9x9.png | Bin .../assets/Space_65x18.png | Bin .../assets/Voldwn_6x6.png | Bin .../assets/Volup_8x6.png | Bin applications/plugins/hid_app/hid.c | 365 ++++++++++++++++++ applications/plugins/hid_app/hid.h | 60 +++ .../hid_ble_10px.png} | Bin applications/plugins/hid_app/hid_usb_10px.png | Bin 0 -> 969 bytes applications/plugins/hid_app/views.h | 9 + .../views/hid_keyboard.c} | 123 +++--- .../plugins/hid_app/views/hid_keyboard.h | 14 + .../views/hid_keynote.c} | 108 +++--- .../plugins/hid_app/views/hid_keynote.h | 14 + .../views/hid_media.c} | 107 ++--- .../plugins/hid_app/views/hid_media.h | 13 + .../views/hid_mouse.c} | 100 ++--- .../plugins/hid_app/views/hid_mouse.h | 17 + .../views/hid_tiktok.c} | 124 +++--- .../plugins/hid_app/views/hid_tiktok.h | 14 + scripts/fbt/appmanifest.py | 1 + scripts/fbt_tools/fbt_extapps.py | 2 +- 51 files changed, 820 insertions(+), 607 deletions(-) delete mode 100644 applications/plugins/bt_hid_app/application.fam delete mode 100644 applications/plugins/bt_hid_app/bt_hid.c delete mode 100644 applications/plugins/bt_hid_app/bt_hid.h delete mode 100644 applications/plugins/bt_hid_app/views/bt_hid_keyboard.h delete mode 100644 applications/plugins/bt_hid_app/views/bt_hid_keynote.h delete mode 100644 applications/plugins/bt_hid_app/views/bt_hid_media.h delete mode 100644 applications/plugins/bt_hid_app/views/bt_hid_mouse.h delete mode 100644 applications/plugins/bt_hid_app/views/bt_hid_tiktok.h create mode 100644 applications/plugins/hid_app/application.fam rename applications/plugins/{bt_hid_app => hid_app}/assets/Arr_dwn_7x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Arr_up_7x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Ble_connected_15x15.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Ble_disconnected_15x15.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/ButtonDown_7x4.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/ButtonLeft_4x7.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/ButtonRight_4x7.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/ButtonUp_7x4.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Button_18x18.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Circles_47x47.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Left_mouse_icon_9x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Like_def_11x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Like_pressed_17x17.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Ok_btn_9x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Ok_btn_pressed_13x13.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pin_arrow_down_7x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pin_arrow_left_9x7.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pin_arrow_right_9x7.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pin_arrow_up_7x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pin_back_arrow_10x8.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Pressed_Button_13x13.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Right_mouse_icon_9x9.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Space_65x18.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Voldwn_6x6.png (100%) rename applications/plugins/{bt_hid_app => hid_app}/assets/Volup_8x6.png (100%) create mode 100644 applications/plugins/hid_app/hid.c create mode 100644 applications/plugins/hid_app/hid.h rename applications/plugins/{bt_hid_app/bt_remote_10px.png => hid_app/hid_ble_10px.png} (100%) create mode 100644 applications/plugins/hid_app/hid_usb_10px.png create mode 100644 applications/plugins/hid_app/views.h rename applications/plugins/{bt_hid_app/views/bt_hid_keyboard.c => hid_app/views/hid_keyboard.c} (80%) create mode 100644 applications/plugins/hid_app/views/hid_keyboard.h rename applications/plugins/{bt_hid_app/views/bt_hid_keynote.c => hid_app/views/hid_keynote.c} (60%) create mode 100644 applications/plugins/hid_app/views/hid_keynote.h rename applications/plugins/{bt_hid_app/views/bt_hid_media.c => hid_app/views/hid_media.c} (59%) create mode 100644 applications/plugins/hid_app/views/hid_media.h rename applications/plugins/{bt_hid_app/views/bt_hid_mouse.c => hid_app/views/hid_mouse.c} (68%) create mode 100644 applications/plugins/hid_app/views/hid_mouse.h rename applications/plugins/{bt_hid_app/views/bt_hid_tiktok.c => hid_app/views/hid_tiktok.c} (59%) create mode 100644 applications/plugins/hid_app/views/hid_tiktok.h diff --git a/applications/plugins/bt_hid_app/application.fam b/applications/plugins/bt_hid_app/application.fam deleted file mode 100644 index 2712fded..00000000 --- a/applications/plugins/bt_hid_app/application.fam +++ /dev/null @@ -1,10 +0,0 @@ -App( - appid="bt_hid", - name="Bluetooth Remote", - apptype=FlipperAppType.EXTERNAL, - entry_point="bt_hid_app", - stack_size=1 * 1024, - fap_category="Tools", - fap_icon="bt_remote_10px.png", - fap_icon_assets="assets", -) diff --git a/applications/plugins/bt_hid_app/bt_hid.c b/applications/plugins/bt_hid_app/bt_hid.c deleted file mode 100644 index 4a77a249..00000000 --- a/applications/plugins/bt_hid_app/bt_hid.c +++ /dev/null @@ -1,216 +0,0 @@ -#include "bt_hid.h" -#include -#include -#include - -#define TAG "BtHidApp" - -enum BtDebugSubmenuIndex { - BtHidSubmenuIndexKeynote, - BtHidSubmenuIndexKeyboard, - BtHidSubmenuIndexMedia, - BtHidSubmenuIndexTikTok, - BtHidSubmenuIndexMouse, -}; - -void bt_hid_submenu_callback(void* context, uint32_t index) { - furi_assert(context); - BtHid* app = context; - if(index == BtHidSubmenuIndexKeynote) { - app->view_id = BtHidViewKeynote; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewKeynote); - } else if(index == BtHidSubmenuIndexKeyboard) { - app->view_id = BtHidViewKeyboard; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewKeyboard); - } else if(index == BtHidSubmenuIndexMedia) { - app->view_id = BtHidViewMedia; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewMedia); - } else if(index == BtHidSubmenuIndexMouse) { - app->view_id = BtHidViewMouse; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewMouse); - } else if(index == BtHidSubmenuIndexTikTok) { - app->view_id = BtHidViewTikTok; - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok); - } -} - -void bt_hid_dialog_callback(DialogExResult result, void* context) { - furi_assert(context); - BtHid* app = context; - if(result == DialogExResultLeft) { - view_dispatcher_stop(app->view_dispatcher); - } else if(result == DialogExResultRight) { - view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view - } else if(result == DialogExResultCenter) { - view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewSubmenu); - } -} - -uint32_t bt_hid_exit_confirm_view(void* context) { - UNUSED(context); - return BtHidViewExitConfirm; -} - -uint32_t bt_hid_exit(void* context) { - UNUSED(context); - return VIEW_NONE; -} - -void bt_hid_connection_status_changed_callback(BtStatus status, void* context) { - furi_assert(context); - BtHid* bt_hid = context; - bool connected = (status == BtStatusConnected); - if(connected) { - notification_internal_message(bt_hid->notifications, &sequence_set_blue_255); - } else { - notification_internal_message(bt_hid->notifications, &sequence_reset_blue); - } - bt_hid_keynote_set_connected_status(bt_hid->bt_hid_keynote, connected); - bt_hid_keyboard_set_connected_status(bt_hid->bt_hid_keyboard, connected); - bt_hid_media_set_connected_status(bt_hid->bt_hid_media, connected); - bt_hid_mouse_set_connected_status(bt_hid->bt_hid_mouse, connected); - bt_hid_tiktok_set_connected_status(bt_hid->bt_hid_tiktok, connected); -} - -BtHid* bt_hid_app_alloc() { - BtHid* app = malloc(sizeof(BtHid)); - - // Gui - app->gui = furi_record_open(RECORD_GUI); - - // Bt - app->bt = furi_record_open(RECORD_BT); - - // Notifications - app->notifications = furi_record_open(RECORD_NOTIFICATION); - - // View dispatcher - app->view_dispatcher = view_dispatcher_alloc(); - view_dispatcher_enable_queue(app->view_dispatcher); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - - // Submenu view - app->submenu = submenu_alloc(); - submenu_add_item( - app->submenu, "Keynote", BtHidSubmenuIndexKeynote, bt_hid_submenu_callback, app); - submenu_add_item( - app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app); - submenu_add_item(app->submenu, "Media", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app); - submenu_add_item( - app->submenu, "TikTok Controller", BtHidSubmenuIndexTikTok, bt_hid_submenu_callback, app); - submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app); - view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewSubmenu, submenu_get_view(app->submenu)); - - // Dialog view - app->dialog = dialog_ex_alloc(); - dialog_ex_set_result_callback(app->dialog, bt_hid_dialog_callback); - dialog_ex_set_context(app->dialog, app); - dialog_ex_set_left_button_text(app->dialog, "Exit"); - dialog_ex_set_right_button_text(app->dialog, "Stay"); - dialog_ex_set_center_button_text(app->dialog, "Menu"); - dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewExitConfirm, dialog_ex_get_view(app->dialog)); - - // Keynote view - app->bt_hid_keynote = bt_hid_keynote_alloc(); - view_set_previous_callback( - bt_hid_keynote_get_view(app->bt_hid_keynote), bt_hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewKeynote, bt_hid_keynote_get_view(app->bt_hid_keynote)); - - // Keyboard view - app->bt_hid_keyboard = bt_hid_keyboard_alloc(); - view_set_previous_callback( - bt_hid_keyboard_get_view(app->bt_hid_keyboard), bt_hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewKeyboard, bt_hid_keyboard_get_view(app->bt_hid_keyboard)); - - // Media view - app->bt_hid_media = bt_hid_media_alloc(); - view_set_previous_callback(bt_hid_media_get_view(app->bt_hid_media), bt_hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewMedia, bt_hid_media_get_view(app->bt_hid_media)); - - // TikTok view - app->bt_hid_tiktok = bt_hid_tiktok_alloc(); - view_set_previous_callback( - bt_hid_tiktok_get_view(app->bt_hid_tiktok), bt_hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewTikTok, bt_hid_tiktok_get_view(app->bt_hid_tiktok)); - - // Mouse view - app->bt_hid_mouse = bt_hid_mouse_alloc(); - view_set_previous_callback(bt_hid_mouse_get_view(app->bt_hid_mouse), bt_hid_exit_confirm_view); - view_dispatcher_add_view( - app->view_dispatcher, BtHidViewMouse, bt_hid_mouse_get_view(app->bt_hid_mouse)); - - // TODO switch to menu after Media is done - app->view_id = BtHidViewSubmenu; - view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); - - return app; -} - -void bt_hid_app_free(BtHid* app) { - furi_assert(app); - - // Reset notification - notification_internal_message(app->notifications, &sequence_reset_blue); - - // Free views - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewSubmenu); - submenu_free(app->submenu); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewExitConfirm); - dialog_ex_free(app->dialog); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewKeynote); - bt_hid_keynote_free(app->bt_hid_keynote); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewKeyboard); - bt_hid_keyboard_free(app->bt_hid_keyboard); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMedia); - bt_hid_media_free(app->bt_hid_media); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMouse); - bt_hid_mouse_free(app->bt_hid_mouse); - view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok); - bt_hid_tiktok_free(app->bt_hid_tiktok); - view_dispatcher_free(app->view_dispatcher); - - // Close records - furi_record_close(RECORD_GUI); - app->gui = NULL; - furi_record_close(RECORD_NOTIFICATION); - app->notifications = NULL; - furi_record_close(RECORD_BT); - app->bt = NULL; - - // Free rest - free(app); -} - -int32_t bt_hid_app(void* p) { - UNUSED(p); - // Switch profile to Hid - BtHid* app = bt_hid_app_alloc(); - bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); - // Change profile - if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) { - FURI_LOG_E(TAG, "Failed to switch profile"); - bt_hid_app_free(app); - return -1; - } - furi_hal_bt_start_advertising(); - - DOLPHIN_DEED(DolphinDeedPluginStart); - - view_dispatcher_run(app->view_dispatcher); - - bt_set_status_changed_callback(app->bt, NULL, NULL); - // Change back profile to Serial - bt_set_profile(app->bt, BtProfileSerial); - - bt_hid_app_free(app); - - return 0; -} diff --git a/applications/plugins/bt_hid_app/bt_hid.h b/applications/plugins/bt_hid_app/bt_hid.h deleted file mode 100644 index 89e8807f..00000000 --- a/applications/plugins/bt_hid_app/bt_hid.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include "views/bt_hid_keynote.h" -#include "views/bt_hid_keyboard.h" -#include "views/bt_hid_media.h" -#include "views/bt_hid_mouse.h" -#include "views/bt_hid_tiktok.h" - -typedef struct { - Bt* bt; - Gui* gui; - NotificationApp* notifications; - ViewDispatcher* view_dispatcher; - Submenu* submenu; - DialogEx* dialog; - BtHidKeynote* bt_hid_keynote; - BtHidKeyboard* bt_hid_keyboard; - BtHidMedia* bt_hid_media; - BtHidMouse* bt_hid_mouse; - BtHidTikTok* bt_hid_tiktok; - uint32_t view_id; -} BtHid; - -typedef enum { - BtHidViewSubmenu, - BtHidViewKeynote, - BtHidViewKeyboard, - BtHidViewMedia, - BtHidViewMouse, - BtHidViewTikTok, - BtHidViewExitConfirm, -} BtHidView; diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.h b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.h deleted file mode 100644 index b2cc928e..00000000 --- a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct BtHidKeyboard BtHidKeyboard; - -BtHidKeyboard* bt_hid_keyboard_alloc(); - -void bt_hid_keyboard_free(BtHidKeyboard* bt_hid_keyboard); - -View* bt_hid_keyboard_get_view(BtHidKeyboard* bt_hid_keyboard); - -void bt_hid_keyboard_set_connected_status(BtHidKeyboard* bt_hid_keyboard, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keynote.h b/applications/plugins/bt_hid_app/views/bt_hid_keynote.h deleted file mode 100644 index 05b12145..00000000 --- a/applications/plugins/bt_hid_app/views/bt_hid_keynote.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct BtHidKeynote BtHidKeynote; - -BtHidKeynote* bt_hid_keynote_alloc(); - -void bt_hid_keynote_free(BtHidKeynote* bt_hid_keynote); - -View* bt_hid_keynote_get_view(BtHidKeynote* bt_hid_keynote); - -void bt_hid_keynote_set_connected_status(BtHidKeynote* bt_hid_keynote, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_media.h b/applications/plugins/bt_hid_app/views/bt_hid_media.h deleted file mode 100644 index 804239dc..00000000 --- a/applications/plugins/bt_hid_app/views/bt_hid_media.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct BtHidMedia BtHidMedia; - -BtHidMedia* bt_hid_media_alloc(); - -void bt_hid_media_free(BtHidMedia* bt_hid_media); - -View* bt_hid_media_get_view(BtHidMedia* bt_hid_media); - -void bt_hid_media_set_connected_status(BtHidMedia* bt_hid_media, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_mouse.h b/applications/plugins/bt_hid_app/views/bt_hid_mouse.h deleted file mode 100644 index a82971d7..00000000 --- a/applications/plugins/bt_hid_app/views/bt_hid_mouse.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct BtHidMouse BtHidMouse; - -BtHidMouse* bt_hid_mouse_alloc(); - -void bt_hid_mouse_free(BtHidMouse* bt_hid_mouse); - -View* bt_hid_mouse_get_view(BtHidMouse* bt_hid_mouse); - -void bt_hid_mouse_set_connected_status(BtHidMouse* bt_hid_mouse, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h b/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h deleted file mode 100644 index 03c9afec..00000000 --- a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -typedef struct BtHidTikTok BtHidTikTok; - -BtHidTikTok* bt_hid_tiktok_alloc(); - -void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok); - -View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok); - -void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected); diff --git a/applications/plugins/hid_app/application.fam b/applications/plugins/hid_app/application.fam new file mode 100644 index 00000000..b8c13e35 --- /dev/null +++ b/applications/plugins/hid_app/application.fam @@ -0,0 +1,24 @@ +App( + appid="hid_usb", + name="USB Remote", + apptype=FlipperAppType.PLUGIN, + entry_point="hid_usb_app", + stack_size=1 * 1024, + fap_category="Tools", + fap_icon="hid_usb_10px.png", + fap_icon_assets="assets", + fap_icon_assets_symbol="hid", +) + + +App( + appid="hid_ble", + name="Bluetooth Remote", + apptype=FlipperAppType.PLUGIN, + entry_point="hid_ble_app", + stack_size=1 * 1024, + fap_category="Tools", + fap_icon="hid_ble_10px.png", + fap_icon_assets="assets", + fap_icon_assets_symbol="hid", +) diff --git a/applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png b/applications/plugins/hid_app/assets/Arr_dwn_7x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png rename to applications/plugins/hid_app/assets/Arr_dwn_7x9.png diff --git a/applications/plugins/bt_hid_app/assets/Arr_up_7x9.png b/applications/plugins/hid_app/assets/Arr_up_7x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Arr_up_7x9.png rename to applications/plugins/hid_app/assets/Arr_up_7x9.png diff --git a/applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png b/applications/plugins/hid_app/assets/Ble_connected_15x15.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png rename to applications/plugins/hid_app/assets/Ble_connected_15x15.png diff --git a/applications/plugins/bt_hid_app/assets/Ble_disconnected_15x15.png b/applications/plugins/hid_app/assets/Ble_disconnected_15x15.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Ble_disconnected_15x15.png rename to applications/plugins/hid_app/assets/Ble_disconnected_15x15.png diff --git a/applications/plugins/bt_hid_app/assets/ButtonDown_7x4.png b/applications/plugins/hid_app/assets/ButtonDown_7x4.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/ButtonDown_7x4.png rename to applications/plugins/hid_app/assets/ButtonDown_7x4.png diff --git a/applications/plugins/bt_hid_app/assets/ButtonLeft_4x7.png b/applications/plugins/hid_app/assets/ButtonLeft_4x7.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/ButtonLeft_4x7.png rename to applications/plugins/hid_app/assets/ButtonLeft_4x7.png diff --git a/applications/plugins/bt_hid_app/assets/ButtonRight_4x7.png b/applications/plugins/hid_app/assets/ButtonRight_4x7.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/ButtonRight_4x7.png rename to applications/plugins/hid_app/assets/ButtonRight_4x7.png diff --git a/applications/plugins/bt_hid_app/assets/ButtonUp_7x4.png b/applications/plugins/hid_app/assets/ButtonUp_7x4.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/ButtonUp_7x4.png rename to applications/plugins/hid_app/assets/ButtonUp_7x4.png diff --git a/applications/plugins/bt_hid_app/assets/Button_18x18.png b/applications/plugins/hid_app/assets/Button_18x18.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Button_18x18.png rename to applications/plugins/hid_app/assets/Button_18x18.png diff --git a/applications/plugins/bt_hid_app/assets/Circles_47x47.png b/applications/plugins/hid_app/assets/Circles_47x47.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Circles_47x47.png rename to applications/plugins/hid_app/assets/Circles_47x47.png diff --git a/applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png b/applications/plugins/hid_app/assets/Left_mouse_icon_9x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png rename to applications/plugins/hid_app/assets/Left_mouse_icon_9x9.png diff --git a/applications/plugins/bt_hid_app/assets/Like_def_11x9.png b/applications/plugins/hid_app/assets/Like_def_11x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Like_def_11x9.png rename to applications/plugins/hid_app/assets/Like_def_11x9.png diff --git a/applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png b/applications/plugins/hid_app/assets/Like_pressed_17x17.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png rename to applications/plugins/hid_app/assets/Like_pressed_17x17.png diff --git a/applications/plugins/bt_hid_app/assets/Ok_btn_9x9.png b/applications/plugins/hid_app/assets/Ok_btn_9x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Ok_btn_9x9.png rename to applications/plugins/hid_app/assets/Ok_btn_9x9.png diff --git a/applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png b/applications/plugins/hid_app/assets/Ok_btn_pressed_13x13.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png rename to applications/plugins/hid_app/assets/Ok_btn_pressed_13x13.png diff --git a/applications/plugins/bt_hid_app/assets/Pin_arrow_down_7x9.png b/applications/plugins/hid_app/assets/Pin_arrow_down_7x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pin_arrow_down_7x9.png rename to applications/plugins/hid_app/assets/Pin_arrow_down_7x9.png diff --git a/applications/plugins/bt_hid_app/assets/Pin_arrow_left_9x7.png b/applications/plugins/hid_app/assets/Pin_arrow_left_9x7.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pin_arrow_left_9x7.png rename to applications/plugins/hid_app/assets/Pin_arrow_left_9x7.png diff --git a/applications/plugins/bt_hid_app/assets/Pin_arrow_right_9x7.png b/applications/plugins/hid_app/assets/Pin_arrow_right_9x7.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pin_arrow_right_9x7.png rename to applications/plugins/hid_app/assets/Pin_arrow_right_9x7.png diff --git a/applications/plugins/bt_hid_app/assets/Pin_arrow_up_7x9.png b/applications/plugins/hid_app/assets/Pin_arrow_up_7x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pin_arrow_up_7x9.png rename to applications/plugins/hid_app/assets/Pin_arrow_up_7x9.png diff --git a/applications/plugins/bt_hid_app/assets/Pin_back_arrow_10x8.png b/applications/plugins/hid_app/assets/Pin_back_arrow_10x8.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pin_back_arrow_10x8.png rename to applications/plugins/hid_app/assets/Pin_back_arrow_10x8.png diff --git a/applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png b/applications/plugins/hid_app/assets/Pressed_Button_13x13.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png rename to applications/plugins/hid_app/assets/Pressed_Button_13x13.png diff --git a/applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png b/applications/plugins/hid_app/assets/Right_mouse_icon_9x9.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png rename to applications/plugins/hid_app/assets/Right_mouse_icon_9x9.png diff --git a/applications/plugins/bt_hid_app/assets/Space_65x18.png b/applications/plugins/hid_app/assets/Space_65x18.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Space_65x18.png rename to applications/plugins/hid_app/assets/Space_65x18.png diff --git a/applications/plugins/bt_hid_app/assets/Voldwn_6x6.png b/applications/plugins/hid_app/assets/Voldwn_6x6.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Voldwn_6x6.png rename to applications/plugins/hid_app/assets/Voldwn_6x6.png diff --git a/applications/plugins/bt_hid_app/assets/Volup_8x6.png b/applications/plugins/hid_app/assets/Volup_8x6.png similarity index 100% rename from applications/plugins/bt_hid_app/assets/Volup_8x6.png rename to applications/plugins/hid_app/assets/Volup_8x6.png diff --git a/applications/plugins/hid_app/hid.c b/applications/plugins/hid_app/hid.c new file mode 100644 index 00000000..2a617fde --- /dev/null +++ b/applications/plugins/hid_app/hid.c @@ -0,0 +1,365 @@ +#include "hid.h" +#include "views.h" +#include +#include + +#define TAG "HidApp" + +enum HidDebugSubmenuIndex { + HidSubmenuIndexKeynote, + HidSubmenuIndexKeyboard, + HidSubmenuIndexMedia, + BtHidSubmenuIndexTikTok, + HidSubmenuIndexMouse, +}; +typedef enum { ConnTypeSubmenuIndexBluetooth, ConnTypeSubmenuIndexUsb } ConnTypeDebugSubmenuIndex; + +static void hid_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + Hid* app = context; + if(index == HidSubmenuIndexKeynote) { + app->view_id = HidViewKeynote; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeynote); + } else if(index == HidSubmenuIndexKeyboard) { + app->view_id = HidViewKeyboard; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewKeyboard); + } else if(index == HidSubmenuIndexMedia) { + app->view_id = HidViewMedia; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMedia); + } else if(index == HidSubmenuIndexMouse) { + app->view_id = HidViewMouse; + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouse); + } else if(index == BtHidSubmenuIndexTikTok) { + app->view_id = BtHidViewTikTok; + view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok); + } +} + +static void bt_hid_connection_status_changed_callback(BtStatus status, void* context) { + furi_assert(context); + Hid* hid = context; + bool connected = (status == BtStatusConnected); + if(connected) { + notification_internal_message(hid->notifications, &sequence_set_blue_255); + } else { + notification_internal_message(hid->notifications, &sequence_reset_blue); + } + hid_keynote_set_connected_status(hid->hid_keynote, connected); + hid_keyboard_set_connected_status(hid->hid_keyboard, connected); + hid_media_set_connected_status(hid->hid_media, connected); + hid_mouse_set_connected_status(hid->hid_mouse, connected); + hid_tiktok_set_connected_status(hid->hid_tiktok, connected); +} + +static void hid_dialog_callback(DialogExResult result, void* context) { + furi_assert(context); + Hid* app = context; + if(result == DialogExResultLeft) { + view_dispatcher_stop(app->view_dispatcher); + } else if(result == DialogExResultRight) { + view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view + } else if(result == DialogExResultCenter) { + view_dispatcher_switch_to_view(app->view_dispatcher, HidViewSubmenu); + } +} + +static uint32_t hid_exit_confirm_view(void* context) { + UNUSED(context); + return HidViewExitConfirm; +} + +static uint32_t hid_exit(void* context) { + UNUSED(context); + return VIEW_NONE; +} + +Hid* hid_alloc(HidTransport transport) { + Hid* app = malloc(sizeof(Hid)); + app->transport = transport; + + // Gui + app->gui = furi_record_open(RECORD_GUI); + + // Bt + app->bt = furi_record_open(RECORD_BT); + + // Notifications + app->notifications = furi_record_open(RECORD_NOTIFICATION); + + // View dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_enable_queue(app->view_dispatcher); + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + // Device Type Submenu view + app->device_type_submenu = submenu_alloc(); + submenu_add_item( + app->device_type_submenu, "Keynote", HidSubmenuIndexKeynote, hid_submenu_callback, app); + submenu_add_item( + app->device_type_submenu, "Keyboard", HidSubmenuIndexKeyboard, hid_submenu_callback, app); + submenu_add_item( + app->device_type_submenu, "Media", HidSubmenuIndexMedia, hid_submenu_callback, app); + submenu_add_item( + app->device_type_submenu, "Mouse", HidSubmenuIndexMouse, hid_submenu_callback, app); + if(app->transport == HidTransportBle) { + submenu_add_item( + app->device_type_submenu, + "TikTok Controller", + BtHidSubmenuIndexTikTok, + hid_submenu_callback, + app); + } + view_set_previous_callback(submenu_get_view(app->device_type_submenu), hid_exit); + view_dispatcher_add_view( + app->view_dispatcher, HidViewSubmenu, submenu_get_view(app->device_type_submenu)); + app->view_id = HidViewSubmenu; + view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); + return app; +} + +Hid* hid_app_alloc_view(void* context) { + furi_assert(context); + Hid* app = context; + // Dialog view + app->dialog = dialog_ex_alloc(); + dialog_ex_set_result_callback(app->dialog, hid_dialog_callback); + dialog_ex_set_context(app->dialog, app); + dialog_ex_set_left_button_text(app->dialog, "Exit"); + dialog_ex_set_right_button_text(app->dialog, "Stay"); + dialog_ex_set_center_button_text(app->dialog, "Menu"); + dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop); + view_dispatcher_add_view( + app->view_dispatcher, HidViewExitConfirm, dialog_ex_get_view(app->dialog)); + + // Keynote view + app->hid_keynote = hid_keynote_alloc(app); + view_set_previous_callback(hid_keynote_get_view(app->hid_keynote), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, HidViewKeynote, hid_keynote_get_view(app->hid_keynote)); + + // Keyboard view + app->hid_keyboard = hid_keyboard_alloc(app); + view_set_previous_callback(hid_keyboard_get_view(app->hid_keyboard), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, HidViewKeyboard, hid_keyboard_get_view(app->hid_keyboard)); + + // Media view + app->hid_media = hid_media_alloc(app); + view_set_previous_callback(hid_media_get_view(app->hid_media), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, HidViewMedia, hid_media_get_view(app->hid_media)); + + // TikTok view + app->hid_tiktok = hid_tiktok_alloc(app); + view_set_previous_callback(hid_tiktok_get_view(app->hid_tiktok), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, BtHidViewTikTok, hid_tiktok_get_view(app->hid_tiktok)); + + // Mouse view + app->hid_mouse = hid_mouse_alloc(app); + view_set_previous_callback(hid_mouse_get_view(app->hid_mouse), hid_exit_confirm_view); + view_dispatcher_add_view( + app->view_dispatcher, HidViewMouse, hid_mouse_get_view(app->hid_mouse)); + + return app; +} + +void hid_free(Hid* app) { + furi_assert(app); + + // Reset notification + notification_internal_message(app->notifications, &sequence_reset_blue); + + // Free views + view_dispatcher_remove_view(app->view_dispatcher, HidViewSubmenu); + submenu_free(app->device_type_submenu); + view_dispatcher_remove_view(app->view_dispatcher, HidViewExitConfirm); + dialog_ex_free(app->dialog); + view_dispatcher_remove_view(app->view_dispatcher, HidViewKeynote); + hid_keynote_free(app->hid_keynote); + view_dispatcher_remove_view(app->view_dispatcher, HidViewKeyboard); + hid_keyboard_free(app->hid_keyboard); + view_dispatcher_remove_view(app->view_dispatcher, HidViewMedia); + hid_media_free(app->hid_media); + view_dispatcher_remove_view(app->view_dispatcher, HidViewMouse); + hid_mouse_free(app->hid_mouse); + view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok); + hid_tiktok_free(app->hid_tiktok); + view_dispatcher_free(app->view_dispatcher); + + // Close records + furi_record_close(RECORD_GUI); + app->gui = NULL; + furi_record_close(RECORD_NOTIFICATION); + app->notifications = NULL; + furi_record_close(RECORD_BT); + app->bt = NULL; + + // Free rest + free(app); +} + +void hid_hal_keyboard_press(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_kb_press(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_kb_press(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_keyboard_release(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_kb_release(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_kb_release(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_keyboard_release_all(Hid* instance) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_kb_release_all(); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_kb_release_all(); + } else { + furi_crash(NULL); + } +} + +void hid_hal_consumer_key_press(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_consumer_key_press(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_consumer_key_press(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_consumer_key_release(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_consumer_key_release(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_consumer_key_release(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_consumer_key_release_all(Hid* instance) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_consumer_key_release_all(); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_kb_release_all(); + } else { + furi_crash(NULL); + } +} + +void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_mouse_move(dx, dy); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_mouse_move(dx, dy); + } else { + furi_crash(NULL); + } +} + +void hid_hal_mouse_scroll(Hid* instance, int8_t delta) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_mouse_scroll(delta); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_mouse_scroll(delta); + } else { + furi_crash(NULL); + } +} + +void hid_hal_mouse_press(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_mouse_press(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_mouse_press(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_mouse_release(Hid* instance, uint16_t event) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_mouse_release(event); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_mouse_release(event); + } else { + furi_crash(NULL); + } +} + +void hid_hal_mouse_release_all(Hid* instance) { + furi_assert(instance); + if(instance->transport == HidTransportBle) { + furi_hal_bt_hid_mouse_release_all(); + } else if(instance->transport == HidTransportUsb) { + furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT); + furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT); + } else { + furi_crash(NULL); + } +} + +int32_t hid_usb_app(void* p) { + UNUSED(p); + Hid* app = hid_alloc(HidTransportUsb); + app = hid_app_alloc_view(app); + FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); + furi_hal_usb_unlock(); + furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true); + + bt_hid_connection_status_changed_callback(BtStatusConnected, app); + + DOLPHIN_DEED(DolphinDeedPluginStart); + + view_dispatcher_run(app->view_dispatcher); + + furi_hal_usb_set_config(usb_mode_prev, NULL); + + hid_free(app); + + return 0; +} + +int32_t hid_ble_app(void* p) { + UNUSED(p); + Hid* app = hid_alloc(HidTransportBle); + app = hid_app_alloc_view(app); + + if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) { + FURI_LOG_E(TAG, "Failed to switch profile"); + } + furi_hal_bt_start_advertising(); + bt_set_status_changed_callback(app->bt, bt_hid_connection_status_changed_callback, app); + + DOLPHIN_DEED(DolphinDeedPluginStart); + + view_dispatcher_run(app->view_dispatcher); + + bt_set_status_changed_callback(app->bt, NULL, NULL); + bt_set_profile(app->bt, BtProfileSerial); + + hid_free(app); + + return 0; +} diff --git a/applications/plugins/hid_app/hid.h b/applications/plugins/hid_app/hid.h new file mode 100644 index 00000000..81ebcf56 --- /dev/null +++ b/applications/plugins/hid_app/hid.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "views/hid_keynote.h" +#include "views/hid_keyboard.h" +#include "views/hid_media.h" +#include "views/hid_mouse.h" +#include "views/hid_tiktok.h" + +typedef enum { + HidTransportUsb, + HidTransportBle, +} HidTransport; + +typedef struct Hid Hid; + +struct Hid { + Bt* bt; + Gui* gui; + NotificationApp* notifications; + ViewDispatcher* view_dispatcher; + Submenu* device_type_submenu; + DialogEx* dialog; + HidKeynote* hid_keynote; + HidKeyboard* hid_keyboard; + HidMedia* hid_media; + HidMouse* hid_mouse; + HidTikTok* hid_tiktok; + + HidTransport transport; + uint32_t view_id; +}; + +void hid_hal_keyboard_press(Hid* instance, uint16_t event); +void hid_hal_keyboard_release(Hid* instance, uint16_t event); +void hid_hal_keyboard_release_all(Hid* instance); + +void hid_hal_consumer_key_press(Hid* instance, uint16_t event); +void hid_hal_consumer_key_release(Hid* instance, uint16_t event); +void hid_hal_consumer_key_release_all(Hid* instance); + +void hid_hal_mouse_move(Hid* instance, int8_t dx, int8_t dy); +void hid_hal_mouse_scroll(Hid* instance, int8_t delta); +void hid_hal_mouse_press(Hid* instance, uint16_t event); +void hid_hal_mouse_release(Hid* instance, uint16_t event); +void hid_hal_mouse_release_all(Hid* instance); \ No newline at end of file diff --git a/applications/plugins/bt_hid_app/bt_remote_10px.png b/applications/plugins/hid_app/hid_ble_10px.png similarity index 100% rename from applications/plugins/bt_hid_app/bt_remote_10px.png rename to applications/plugins/hid_app/hid_ble_10px.png diff --git a/applications/plugins/hid_app/hid_usb_10px.png b/applications/plugins/hid_app/hid_usb_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..415de7d2304fe982c025b2b9a942abbf0a2b6dd0 GIT binary patch literal 969 zcmaJ=J#W)M7(OY0prTdS3e(9IQYsOjefe;0)l|h!Xha;MG(g5)>`P;{_8I$1oJb(V z#>Co{9{@i91|(QuX5%*?v9pwOnxqT_55D(az0dQ0J@>lZy1%+|YXtzX+Ss!@;>_%o zt2y!i@N?&lIBxPQduOaNrjU+e?;YX%)UR2L%LyN@}>atRF6-9xXE~}dAVr@YBcOX_U zM#>gat3`~BQpG5%aP~Eh*gj89{x|#<%&i_M$ zU=f}04!x-NpTtRb98uJv2|I~hvAe-WmMSu=m=ez7E@Q{@LAHmCvt-C3h|9793l4Gp zF!O9qA&z4-!i1C1r48GZ1c~hXo`JDuS-aJ0wOrd$)taqWN;ON>tZH4WV;fs@tj*k$ zfQEdI^)9g5QfwxOAQG8v8vD3;Z_1q-{ zl$i_hipxU&G!&YTg}8q|eDGX6j4SPCw{~`RCd@~lzrPU2?S{SEO@H(cJnv<$o(G-l ph0_~rZ>7^_`EovpzT_W+OY7j;8rXcd{ -#include -#include #include #include +#include "../hid.h" +#include "hid_icons.h" -#include "bt_hid_icons.h" +#define TAG "HidKeyboard" -struct BtHidKeyboard { +struct HidKeyboard { View* view; + Hid* hid; }; typedef struct { @@ -24,7 +25,7 @@ typedef struct { bool back_pressed; bool connected; char key_string[5]; -} BtHidKeyboardModel; +} HidKeyboardModel; typedef struct { uint8_t width; @@ -32,13 +33,12 @@ typedef struct { const Icon* icon; char* shift_key; uint8_t value; -} BtHidKeyboardKey; +} HidKeyboardKey; typedef struct { int8_t x; int8_t y; -} BtHidKeyboardPoint; - +} HidKeyboardPoint; // 4 BY 12 #define MARGIN_TOP 0 #define MARGIN_LEFT 4 @@ -49,7 +49,7 @@ typedef struct { #define COLUMN_COUNT 12 // 0 width items are not drawn, but there value is used -const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { +const HidKeyboardKey hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { { {.width = 1, .icon = NULL, .key = "1", .shift_key = "!", .value = HID_KEYBOARD_1}, {.width = 1, .icon = NULL, .key = "2", .shift_key = "@", .value = HID_KEYBOARD_2}, @@ -112,7 +112,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { }, { {.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT}, - {.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA}, + {.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYBOARD_COMMA}, {.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT}, {.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR}, {.width = 0, .value = HID_KEYBOARD_SPACEBAR}, @@ -140,19 +140,19 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = { }, }; -static void bt_hid_keyboard_to_upper(char* str) { +static void hid_keyboard_to_upper(char* str) { while(*str) { *str = toupper((unsigned char)*str); str++; } } -static void bt_hid_keyboard_draw_key( +static void hid_keyboard_draw_key( Canvas* canvas, - BtHidKeyboardModel* model, + HidKeyboardModel* model, uint8_t x, uint8_t y, - BtHidKeyboardKey key, + HidKeyboardKey key, bool selected) { if(!key.width) return; @@ -190,7 +190,7 @@ static void bt_hid_keyboard_draw_key( if((model->ctrl && key.value == HID_KEYBOARD_L_CTRL) || (model->alt && key.value == HID_KEYBOARD_L_ALT) || (model->gui && key.value == HID_KEYBOARD_L_GUI)) { - bt_hid_keyboard_to_upper(model->key_string); + hid_keyboard_to_upper(model->key_string); } canvas_draw_str_aligned( canvas, @@ -202,9 +202,9 @@ static void bt_hid_keyboard_draw_key( } } -static void bt_hid_keyboard_draw_callback(Canvas* canvas, void* context) { +static void hid_keyboard_draw_callback(Canvas* canvas, void* context) { furi_assert(context); - BtHidKeyboardModel* model = context; + HidKeyboardModel* model = context; // Header if(!model->connected) { @@ -225,17 +225,17 @@ static void bt_hid_keyboard_draw_callback(Canvas* canvas, void* context) { // Start shifting the all keys up if on the next row (Scrolling) uint8_t initY = model->y - 4 > 0 ? model->y - 4 : 0; for(uint8_t y = initY; y < ROW_COUNT; y++) { - const BtHidKeyboardKey* keyboardKeyRow = bt_hid_keyboard_keyset[y]; + const HidKeyboardKey* keyboardKeyRow = hid_keyboard_keyset[y]; uint8_t x = 0; for(uint8_t i = 0; i < COLUMN_COUNT; i++) { - BtHidKeyboardKey key = keyboardKeyRow[i]; + HidKeyboardKey key = keyboardKeyRow[i]; // Select when the button is hovered // Select if the button is hovered within its width // Select if back is clicked and its the backspace key // Deselect when the button clicked or not hovered bool keySelected = (x <= model->x && model->x < (x + key.width)) && y == model->y; bool backSelected = model->back_pressed && key.value == HID_KEYBOARD_DELETE; - bt_hid_keyboard_draw_key( + hid_keyboard_draw_key( canvas, model, x, @@ -247,8 +247,8 @@ static void bt_hid_keyboard_draw_callback(Canvas* canvas, void* context) { } } -static uint8_t bt_hid_keyboard_get_selected_key(BtHidKeyboardModel* model) { - BtHidKeyboardKey key = bt_hid_keyboard_keyset[model->y][model->x]; +static uint8_t hid_keyboard_get_selected_key(HidKeyboardModel* model) { + HidKeyboardKey key = hid_keyboard_keyset[model->y][model->x]; // Use upper case if shift is toggled bool useUppercase = model->shift; // Check if the key has an upper case version @@ -259,34 +259,34 @@ static uint8_t bt_hid_keyboard_get_selected_key(BtHidKeyboardModel* model) { return key.value; } -static void bt_hid_keyboard_get_select_key(BtHidKeyboardModel* model, BtHidKeyboardPoint delta) { +static void hid_keyboard_get_select_key(HidKeyboardModel* model, HidKeyboardPoint delta) { // Keep going until a valid spot is found, this allows for nulls and zero width keys in the map do { if(((int8_t)model->y) + delta.y < 0) model->y = ROW_COUNT - 1; else model->y = (model->y + delta.y) % ROW_COUNT; - } while(delta.y != 0 && bt_hid_keyboard_keyset[model->y][model->x].value == 0); + } while(delta.y != 0 && hid_keyboard_keyset[model->y][model->x].value == 0); do { if(((int8_t)model->x) + delta.x < 0) model->x = COLUMN_COUNT - 1; else model->x = (model->x + delta.x) % COLUMN_COUNT; - } while(delta.x != 0 && bt_hid_keyboard_keyset[model->y][model->x].width == + } while(delta.x != 0 && hid_keyboard_keyset[model->y][model->x].width == 0); // Skip zero width keys, pretend they are one key } -static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* event) { +static void hid_keyboard_process(HidKeyboard* hid_keyboard, InputEvent* event) { with_view_model( - bt_hid_keyboard->view, - BtHidKeyboardModel * model, + hid_keyboard->view, + HidKeyboardModel * model, { if(event->key == InputKeyOk) { if(event->type == InputTypePress) { model->ok_pressed = true; } else if(event->type == InputTypeLong || event->type == InputTypeShort) { - model->last_key_code = bt_hid_keyboard_get_selected_key(model); + model->last_key_code = hid_keyboard_get_selected_key(model); // Toggle the modifier key when clicked, and click the key if(model->last_key_code == HID_KEYBOARD_L_SHIFT) { @@ -314,10 +314,12 @@ static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* else model->modifier_code &= ~KEY_MOD_LEFT_GUI; } - furi_hal_bt_hid_kb_press(model->modifier_code | model->last_key_code); + hid_hal_keyboard_press( + hid_keyboard->hid, model->modifier_code | model->last_key_code); } else if(event->type == InputTypeRelease) { // Release happens after short and long presses - furi_hal_bt_hid_kb_release(model->modifier_code | model->last_key_code); + hid_hal_keyboard_release( + hid_keyboard->hid, model->modifier_code | model->last_key_code); model->ok_pressed = false; } } else if(event->key == InputKeyBack) { @@ -325,66 +327,67 @@ static void bt_hid_keyboard_process(BtHidKeyboard* bt_hid_keyboard, InputEvent* if(event->type == InputTypePress) { model->back_pressed = true; } else if(event->type == InputTypeShort) { - furi_hal_bt_hid_kb_press(HID_KEYBOARD_DELETE); - furi_hal_bt_hid_kb_release(HID_KEYBOARD_DELETE); + hid_hal_keyboard_press(hid_keyboard->hid, HID_KEYBOARD_DELETE); + hid_hal_keyboard_release(hid_keyboard->hid, HID_KEYBOARD_DELETE); } else if(event->type == InputTypeRelease) { model->back_pressed = false; } } else if(event->type == InputTypePress || event->type == InputTypeRepeat) { // Cycle the selected keys if(event->key == InputKeyUp) { - bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 0, .y = -1}); + hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 0, .y = -1}); } else if(event->key == InputKeyDown) { - bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 0, .y = 1}); + hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 0, .y = 1}); } else if(event->key == InputKeyLeft) { - bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = -1, .y = 0}); + hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = -1, .y = 0}); } else if(event->key == InputKeyRight) { - bt_hid_keyboard_get_select_key(model, (BtHidKeyboardPoint){.x = 1, .y = 0}); + hid_keyboard_get_select_key(model, (HidKeyboardPoint){.x = 1, .y = 0}); } } }, true); } -static bool bt_hid_keyboard_input_callback(InputEvent* event, void* context) { +static bool hid_keyboard_input_callback(InputEvent* event, void* context) { furi_assert(context); - BtHidKeyboard* bt_hid_keyboard = context; + HidKeyboard* hid_keyboard = context; bool consumed = false; if(event->type == InputTypeLong && event->key == InputKeyBack) { - furi_hal_bt_hid_kb_release_all(); + hid_hal_keyboard_release_all(hid_keyboard->hid); } else { - bt_hid_keyboard_process(bt_hid_keyboard, event); + hid_keyboard_process(hid_keyboard, event); consumed = true; } return consumed; } -BtHidKeyboard* bt_hid_keyboard_alloc() { - BtHidKeyboard* bt_hid_keyboard = malloc(sizeof(BtHidKeyboard)); - bt_hid_keyboard->view = view_alloc(); - view_set_context(bt_hid_keyboard->view, bt_hid_keyboard); - view_allocate_model(bt_hid_keyboard->view, ViewModelTypeLocking, sizeof(BtHidKeyboardModel)); - view_set_draw_callback(bt_hid_keyboard->view, bt_hid_keyboard_draw_callback); - view_set_input_callback(bt_hid_keyboard->view, bt_hid_keyboard_input_callback); +HidKeyboard* hid_keyboard_alloc(Hid* bt_hid) { + HidKeyboard* hid_keyboard = malloc(sizeof(HidKeyboard)); + hid_keyboard->view = view_alloc(); + hid_keyboard->hid = bt_hid; + view_set_context(hid_keyboard->view, hid_keyboard); + view_allocate_model(hid_keyboard->view, ViewModelTypeLocking, sizeof(HidKeyboardModel)); + view_set_draw_callback(hid_keyboard->view, hid_keyboard_draw_callback); + view_set_input_callback(hid_keyboard->view, hid_keyboard_input_callback); - return bt_hid_keyboard; + return hid_keyboard; } -void bt_hid_keyboard_free(BtHidKeyboard* bt_hid_keyboard) { - furi_assert(bt_hid_keyboard); - view_free(bt_hid_keyboard->view); - free(bt_hid_keyboard); +void hid_keyboard_free(HidKeyboard* hid_keyboard) { + furi_assert(hid_keyboard); + view_free(hid_keyboard->view); + free(hid_keyboard); } -View* bt_hid_keyboard_get_view(BtHidKeyboard* bt_hid_keyboard) { - furi_assert(bt_hid_keyboard); - return bt_hid_keyboard->view; +View* hid_keyboard_get_view(HidKeyboard* hid_keyboard) { + furi_assert(hid_keyboard); + return hid_keyboard->view; } -void bt_hid_keyboard_set_connected_status(BtHidKeyboard* bt_hid_keyboard, bool connected) { - furi_assert(bt_hid_keyboard); +void hid_keyboard_set_connected_status(HidKeyboard* hid_keyboard, bool connected) { + furi_assert(hid_keyboard); with_view_model( - bt_hid_keyboard->view, BtHidKeyboardModel * model, { model->connected = connected; }, true); + hid_keyboard->view, HidKeyboardModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/hid_app/views/hid_keyboard.h b/applications/plugins/hid_app/views/hid_keyboard.h new file mode 100644 index 00000000..71277136 --- /dev/null +++ b/applications/plugins/hid_app/views/hid_keyboard.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidKeyboard HidKeyboard; + +HidKeyboard* hid_keyboard_alloc(Hid* bt_hid); + +void hid_keyboard_free(HidKeyboard* hid_keyboard); + +View* hid_keyboard_get_view(HidKeyboard* hid_keyboard); + +void hid_keyboard_set_connected_status(HidKeyboard* hid_keyboard, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keynote.c b/applications/plugins/hid_app/views/hid_keynote.c similarity index 60% rename from applications/plugins/bt_hid_app/views/bt_hid_keynote.c rename to applications/plugins/hid_app/views/hid_keynote.c index 0e81c5fa..c95f4278 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_keynote.c +++ b/applications/plugins/hid_app/views/hid_keynote.c @@ -1,13 +1,14 @@ -#include "bt_hid_keynote.h" -#include -#include -#include +#include "hid_keynote.h" #include +#include "../hid.h" -#include "bt_hid_icons.h" +#include "hid_icons.h" -struct BtHidKeynote { +#define TAG "HidKeynote" + +struct HidKeynote { View* view; + Hid* hid; }; typedef struct { @@ -18,9 +19,9 @@ typedef struct { bool ok_pressed; bool back_pressed; bool connected; -} BtHidKeynoteModel; +} HidKeynoteModel; -static void bt_hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { +static void hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { canvas_draw_triangle(canvas, x, y, 5, 3, dir); if(dir == CanvasDirectionBottomToTop) { canvas_draw_line(canvas, x, y + 6, x, y - 1); @@ -33,9 +34,9 @@ static void bt_hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, Canv } } -static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { +static void hid_keynote_draw_callback(Canvas* canvas, void* context) { furi_assert(context); - BtHidKeynoteModel* model = context; + HidKeynoteModel* model = context; // Header if(model->connected) { @@ -56,7 +57,7 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { elements_slightly_rounded_box(canvas, 24, 26, 13, 13); canvas_set_color(canvas, ColorWhite); } - bt_hid_keynote_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop); + hid_keynote_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop); canvas_set_color(canvas, ColorBlack); // Down @@ -65,7 +66,7 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { elements_slightly_rounded_box(canvas, 24, 47, 13, 13); canvas_set_color(canvas, ColorWhite); } - bt_hid_keynote_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom); + hid_keynote_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom); canvas_set_color(canvas, ColorBlack); // Left @@ -74,7 +75,7 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { elements_slightly_rounded_box(canvas, 3, 47, 13, 13); canvas_set_color(canvas, ColorWhite); } - bt_hid_keynote_draw_arrow(canvas, 7, 53, CanvasDirectionRightToLeft); + hid_keynote_draw_arrow(canvas, 7, 53, CanvasDirectionRightToLeft); canvas_set_color(canvas, ColorBlack); // Right @@ -83,7 +84,7 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { elements_slightly_rounded_box(canvas, 45, 47, 13, 13); canvas_set_color(canvas, ColorWhite); } - bt_hid_keynote_draw_arrow(canvas, 53, 53, CanvasDirectionLeftToRight); + hid_keynote_draw_arrow(canvas, 53, 53, CanvasDirectionLeftToRight); canvas_set_color(canvas, ColorBlack); // Ok @@ -106,100 +107,101 @@ static void bt_hid_keynote_draw_callback(Canvas* canvas, void* context) { elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Back"); } -static void bt_hid_keynote_process(BtHidKeynote* bt_hid_keynote, InputEvent* event) { +static void hid_keynote_process(HidKeynote* hid_keynote, InputEvent* event) { with_view_model( - bt_hid_keynote->view, - BtHidKeynoteModel * model, + hid_keynote->view, + HidKeynoteModel * model, { if(event->type == InputTypePress) { if(event->key == InputKeyUp) { model->up_pressed = true; - furi_hal_bt_hid_kb_press(HID_KEYBOARD_UP_ARROW); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_UP_ARROW); } else if(event->key == InputKeyDown) { model->down_pressed = true; - furi_hal_bt_hid_kb_press(HID_KEYBOARD_DOWN_ARROW); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_DOWN_ARROW); } else if(event->key == InputKeyLeft) { model->left_pressed = true; - furi_hal_bt_hid_kb_press(HID_KEYBOARD_LEFT_ARROW); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_LEFT_ARROW); } else if(event->key == InputKeyRight) { model->right_pressed = true; - furi_hal_bt_hid_kb_press(HID_KEYBOARD_RIGHT_ARROW); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_RIGHT_ARROW); } else if(event->key == InputKeyOk) { model->ok_pressed = true; - furi_hal_bt_hid_kb_press(HID_KEYBOARD_SPACEBAR); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_SPACEBAR); } else if(event->key == InputKeyBack) { model->back_pressed = true; } } else if(event->type == InputTypeRelease) { if(event->key == InputKeyUp) { model->up_pressed = false; - furi_hal_bt_hid_kb_release(HID_KEYBOARD_UP_ARROW); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_UP_ARROW); } else if(event->key == InputKeyDown) { model->down_pressed = false; - furi_hal_bt_hid_kb_release(HID_KEYBOARD_DOWN_ARROW); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_DOWN_ARROW); } else if(event->key == InputKeyLeft) { model->left_pressed = false; - furi_hal_bt_hid_kb_release(HID_KEYBOARD_LEFT_ARROW); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_LEFT_ARROW); } else if(event->key == InputKeyRight) { model->right_pressed = false; - furi_hal_bt_hid_kb_release(HID_KEYBOARD_RIGHT_ARROW); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_RIGHT_ARROW); } else if(event->key == InputKeyOk) { model->ok_pressed = false; - furi_hal_bt_hid_kb_release(HID_KEYBOARD_SPACEBAR); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_SPACEBAR); } else if(event->key == InputKeyBack) { model->back_pressed = false; } } else if(event->type == InputTypeShort) { if(event->key == InputKeyBack) { - furi_hal_bt_hid_kb_press(HID_KEYBOARD_DELETE); - furi_hal_bt_hid_kb_release(HID_KEYBOARD_DELETE); - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_AC_BACK); - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_AC_BACK); + hid_hal_keyboard_press(hid_keynote->hid, HID_KEYBOARD_DELETE); + hid_hal_keyboard_release(hid_keynote->hid, HID_KEYBOARD_DELETE); + hid_hal_consumer_key_press(hid_keynote->hid, HID_CONSUMER_AC_BACK); + hid_hal_consumer_key_release(hid_keynote->hid, HID_CONSUMER_AC_BACK); } } }, true); } -static bool bt_hid_keynote_input_callback(InputEvent* event, void* context) { +static bool hid_keynote_input_callback(InputEvent* event, void* context) { furi_assert(context); - BtHidKeynote* bt_hid_keynote = context; + HidKeynote* hid_keynote = context; bool consumed = false; if(event->type == InputTypeLong && event->key == InputKeyBack) { - furi_hal_bt_hid_kb_release_all(); + hid_hal_keyboard_release_all(hid_keynote->hid); } else { - bt_hid_keynote_process(bt_hid_keynote, event); + hid_keynote_process(hid_keynote, event); consumed = true; } return consumed; } -BtHidKeynote* bt_hid_keynote_alloc() { - BtHidKeynote* bt_hid_keynote = malloc(sizeof(BtHidKeynote)); - bt_hid_keynote->view = view_alloc(); - view_set_context(bt_hid_keynote->view, bt_hid_keynote); - view_allocate_model(bt_hid_keynote->view, ViewModelTypeLocking, sizeof(BtHidKeynoteModel)); - view_set_draw_callback(bt_hid_keynote->view, bt_hid_keynote_draw_callback); - view_set_input_callback(bt_hid_keynote->view, bt_hid_keynote_input_callback); +HidKeynote* hid_keynote_alloc(Hid* hid) { + HidKeynote* hid_keynote = malloc(sizeof(HidKeynote)); + hid_keynote->view = view_alloc(); + hid_keynote->hid = hid; + view_set_context(hid_keynote->view, hid_keynote); + view_allocate_model(hid_keynote->view, ViewModelTypeLocking, sizeof(HidKeynoteModel)); + view_set_draw_callback(hid_keynote->view, hid_keynote_draw_callback); + view_set_input_callback(hid_keynote->view, hid_keynote_input_callback); - return bt_hid_keynote; + return hid_keynote; } -void bt_hid_keynote_free(BtHidKeynote* bt_hid_keynote) { - furi_assert(bt_hid_keynote); - view_free(bt_hid_keynote->view); - free(bt_hid_keynote); +void hid_keynote_free(HidKeynote* hid_keynote) { + furi_assert(hid_keynote); + view_free(hid_keynote->view); + free(hid_keynote); } -View* bt_hid_keynote_get_view(BtHidKeynote* bt_hid_keynote) { - furi_assert(bt_hid_keynote); - return bt_hid_keynote->view; +View* hid_keynote_get_view(HidKeynote* hid_keynote) { + furi_assert(hid_keynote); + return hid_keynote->view; } -void bt_hid_keynote_set_connected_status(BtHidKeynote* bt_hid_keynote, bool connected) { - furi_assert(bt_hid_keynote); +void hid_keynote_set_connected_status(HidKeynote* hid_keynote, bool connected) { + furi_assert(hid_keynote); with_view_model( - bt_hid_keynote->view, BtHidKeynoteModel * model, { model->connected = connected; }, true); + hid_keynote->view, HidKeynoteModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/hid_app/views/hid_keynote.h b/applications/plugins/hid_app/views/hid_keynote.h new file mode 100644 index 00000000..4d4a0a9b --- /dev/null +++ b/applications/plugins/hid_app/views/hid_keynote.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidKeynote HidKeynote; + +HidKeynote* hid_keynote_alloc(Hid* bt_hid); + +void hid_keynote_free(HidKeynote* hid_keynote); + +View* hid_keynote_get_view(HidKeynote* hid_keynote); + +void hid_keynote_set_connected_status(HidKeynote* hid_keynote, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_media.c b/applications/plugins/hid_app/views/hid_media.c similarity index 59% rename from applications/plugins/bt_hid_app/views/bt_hid_media.c rename to applications/plugins/hid_app/views/hid_media.c index df7349a9..5d764f73 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_media.c +++ b/applications/plugins/hid_app/views/hid_media.c @@ -1,13 +1,17 @@ -#include "bt_hid_media.h" +#include "hid_media.h" #include #include #include #include +#include "../hid.h" -#include "bt_hid_icons.h" +#include "hid_icons.h" -struct BtHidMedia { +#define TAG "HidMedia" + +struct HidMedia { View* view; + Hid* hid; }; typedef struct { @@ -17,9 +21,9 @@ typedef struct { bool down_pressed; bool ok_pressed; bool connected; -} BtHidMediaModel; +} HidMediaModel; -static void bt_hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { +static void hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { canvas_draw_triangle(canvas, x, y, 5, 3, dir); if(dir == CanvasDirectionBottomToTop) { canvas_draw_dot(canvas, x, y - 1); @@ -32,9 +36,9 @@ static void bt_hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, Canvas } } -static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { +static void hid_media_draw_callback(Canvas* canvas, void* context) { furi_assert(context); - BtHidMediaModel* model = context; + HidMediaModel* model = context; // Header if(model->connected) { @@ -76,8 +80,8 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - bt_hid_media_draw_arrow(canvas, 82, 31, CanvasDirectionRightToLeft); - bt_hid_media_draw_arrow(canvas, 86, 31, CanvasDirectionRightToLeft); + hid_media_draw_arrow(canvas, 82, 31, CanvasDirectionRightToLeft); + hid_media_draw_arrow(canvas, 86, 31, CanvasDirectionRightToLeft); canvas_set_color(canvas, ColorBlack); // Right @@ -87,8 +91,8 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { canvas_set_bitmap_mode(canvas, 0); canvas_set_color(canvas, ColorWhite); } - bt_hid_media_draw_arrow(canvas, 112, 31, CanvasDirectionLeftToRight); - bt_hid_media_draw_arrow(canvas, 116, 31, CanvasDirectionLeftToRight); + hid_media_draw_arrow(canvas, 112, 31, CanvasDirectionLeftToRight); + hid_media_draw_arrow(canvas, 116, 31, CanvasDirectionLeftToRight); canvas_set_color(canvas, ColorBlack); // Ok @@ -96,7 +100,7 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { canvas_draw_icon(canvas, 93, 25, &I_Pressed_Button_13x13); canvas_set_color(canvas, ColorWhite); } - bt_hid_media_draw_arrow(canvas, 96, 31, CanvasDirectionLeftToRight); + hid_media_draw_arrow(canvas, 96, 31, CanvasDirectionLeftToRight); canvas_draw_line(canvas, 100, 29, 100, 33); canvas_draw_line(canvas, 102, 29, 102, 33); canvas_set_color(canvas, ColorBlack); @@ -107,100 +111,101 @@ static void bt_hid_media_draw_callback(Canvas* canvas, void* context) { elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); } -static void bt_hid_media_process_press(BtHidMedia* bt_hid_media, InputEvent* event) { +static void hid_media_process_press(HidMedia* hid_media, InputEvent* event) { with_view_model( - bt_hid_media->view, - BtHidMediaModel * model, + hid_media->view, + HidMediaModel * model, { if(event->key == InputKeyUp) { model->up_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT); + hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyDown) { model->down_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT); + hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_VOLUME_DECREMENT); } else if(event->key == InputKeyLeft) { model->left_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_SCAN_PREVIOUS_TRACK); + hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_SCAN_PREVIOUS_TRACK); } else if(event->key == InputKeyRight) { model->right_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_SCAN_NEXT_TRACK); + hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_SCAN_NEXT_TRACK); } else if(event->key == InputKeyOk) { model->ok_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_PLAY_PAUSE); + hid_hal_consumer_key_press(hid_media->hid, HID_CONSUMER_PLAY_PAUSE); } }, true); } -static void bt_hid_media_process_release(BtHidMedia* bt_hid_media, InputEvent* event) { +static void hid_media_process_release(HidMedia* hid_media, InputEvent* event) { with_view_model( - bt_hid_media->view, - BtHidMediaModel * model, + hid_media->view, + HidMediaModel * model, { if(event->key == InputKeyUp) { model->up_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT); + hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyDown) { model->down_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT); + hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_VOLUME_DECREMENT); } else if(event->key == InputKeyLeft) { model->left_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_SCAN_PREVIOUS_TRACK); + hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_SCAN_PREVIOUS_TRACK); } else if(event->key == InputKeyRight) { model->right_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_SCAN_NEXT_TRACK); + hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_SCAN_NEXT_TRACK); } else if(event->key == InputKeyOk) { model->ok_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_PLAY_PAUSE); + hid_hal_consumer_key_release(hid_media->hid, HID_CONSUMER_PLAY_PAUSE); } }, true); } -static bool bt_hid_media_input_callback(InputEvent* event, void* context) { +static bool hid_media_input_callback(InputEvent* event, void* context) { furi_assert(context); - BtHidMedia* bt_hid_media = context; + HidMedia* hid_media = context; bool consumed = false; if(event->type == InputTypePress) { - bt_hid_media_process_press(bt_hid_media, event); + hid_media_process_press(hid_media, event); consumed = true; } else if(event->type == InputTypeRelease) { - bt_hid_media_process_release(bt_hid_media, event); + hid_media_process_release(hid_media, event); consumed = true; } else if(event->type == InputTypeShort) { if(event->key == InputKeyBack) { - furi_hal_bt_hid_consumer_key_release_all(); + hid_hal_consumer_key_release_all(hid_media->hid); } } return consumed; } -BtHidMedia* bt_hid_media_alloc() { - BtHidMedia* bt_hid_media = malloc(sizeof(BtHidMedia)); - bt_hid_media->view = view_alloc(); - view_set_context(bt_hid_media->view, bt_hid_media); - view_allocate_model(bt_hid_media->view, ViewModelTypeLocking, sizeof(BtHidMediaModel)); - view_set_draw_callback(bt_hid_media->view, bt_hid_media_draw_callback); - view_set_input_callback(bt_hid_media->view, bt_hid_media_input_callback); +HidMedia* hid_media_alloc(Hid* hid) { + HidMedia* hid_media = malloc(sizeof(HidMedia)); + hid_media->view = view_alloc(); + hid_media->hid = hid; + view_set_context(hid_media->view, hid_media); + view_allocate_model(hid_media->view, ViewModelTypeLocking, sizeof(HidMediaModel)); + view_set_draw_callback(hid_media->view, hid_media_draw_callback); + view_set_input_callback(hid_media->view, hid_media_input_callback); - return bt_hid_media; + return hid_media; } -void bt_hid_media_free(BtHidMedia* bt_hid_media) { - furi_assert(bt_hid_media); - view_free(bt_hid_media->view); - free(bt_hid_media); +void hid_media_free(HidMedia* hid_media) { + furi_assert(hid_media); + view_free(hid_media->view); + free(hid_media); } -View* bt_hid_media_get_view(BtHidMedia* bt_hid_media) { - furi_assert(bt_hid_media); - return bt_hid_media->view; +View* hid_media_get_view(HidMedia* hid_media) { + furi_assert(hid_media); + return hid_media->view; } -void bt_hid_media_set_connected_status(BtHidMedia* bt_hid_media, bool connected) { - furi_assert(bt_hid_media); +void hid_media_set_connected_status(HidMedia* hid_media, bool connected) { + furi_assert(hid_media); with_view_model( - bt_hid_media->view, BtHidMediaModel * model, { model->connected = connected; }, true); + hid_media->view, HidMediaModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/hid_app/views/hid_media.h b/applications/plugins/hid_app/views/hid_media.h new file mode 100644 index 00000000..4aa51dc1 --- /dev/null +++ b/applications/plugins/hid_app/views/hid_media.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +typedef struct HidMedia HidMedia; + +HidMedia* hid_media_alloc(); + +void hid_media_free(HidMedia* hid_media); + +View* hid_media_get_view(HidMedia* hid_media); + +void hid_media_set_connected_status(HidMedia* hid_media, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_mouse.c b/applications/plugins/hid_app/views/hid_mouse.c similarity index 68% rename from applications/plugins/bt_hid_app/views/bt_hid_mouse.c rename to applications/plugins/hid_app/views/hid_mouse.c index bd48bab1..d1d76c15 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_mouse.c +++ b/applications/plugins/hid_app/views/hid_mouse.c @@ -1,16 +1,15 @@ -#include "bt_hid_mouse.h" -#include -#include -#include +#include "hid_mouse.h" #include +#include "../hid.h" -#include "bt_hid_icons.h" +#include "hid_icons.h" -struct BtHidMouse { +#define TAG "HidMouse" + +struct HidMouse { View* view; + Hid* hid; }; -#define MOUSE_MOVE_SHORT 5 -#define MOUSE_MOVE_LONG 20 typedef struct { bool left_pressed; @@ -21,11 +20,11 @@ typedef struct { bool left_mouse_held; bool right_mouse_pressed; bool connected; -} BtHidMouseModel; +} HidMouseModel; -static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) { +static void hid_mouse_draw_callback(Canvas* canvas, void* context) { furi_assert(context); - BtHidMouseModel* model = context; + HidMouseModel* model = context; // Header if(model->connected) { @@ -103,15 +102,15 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) { } } -static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { +static void hid_mouse_process(HidMouse* hid_mouse, InputEvent* event) { with_view_model( - bt_hid_mouse->view, - BtHidMouseModel * model, + hid_mouse->view, + HidMouseModel * model, { if(event->key == InputKeyBack) { if(event->type == InputTypeShort) { - furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT); - furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_RIGHT); + hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_RIGHT); + hid_hal_mouse_release(hid_mouse->hid, HID_MOUSE_BTN_RIGHT); } else if(event->type == InputTypePress) { model->right_mouse_pressed = true; } else if(event->type == InputTypeRelease) { @@ -120,11 +119,12 @@ static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { } else if(event->key == InputKeyOk) { if(event->type == InputTypeShort) { // Just release if it was being held before - if(!model->left_mouse_held) furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); - furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT); + if(!model->left_mouse_held) + hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_LEFT); + hid_hal_mouse_release(hid_mouse->hid, HID_MOUSE_BTN_LEFT); model->left_mouse_held = false; } else if(event->type == InputTypeLong) { - furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); + hid_hal_mouse_press(hid_mouse->hid, HID_MOUSE_BTN_LEFT); model->left_mouse_held = true; model->left_mouse_pressed = true; } else if(event->type == InputTypePress) { @@ -133,40 +133,39 @@ static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { // Only release if it wasn't a long press if(!model->left_mouse_held) model->left_mouse_pressed = false; } - } else if(event->key == InputKeyRight) { if(event->type == InputTypePress) { model->right_pressed = true; - furi_hal_bt_hid_mouse_move(MOUSE_MOVE_SHORT, 0); + hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_SHORT, 0); } else if(event->type == InputTypeRepeat) { - furi_hal_bt_hid_mouse_move(MOUSE_MOVE_LONG, 0); + hid_hal_mouse_move(hid_mouse->hid, MOUSE_MOVE_LONG, 0); } else if(event->type == InputTypeRelease) { model->right_pressed = false; } } else if(event->key == InputKeyLeft) { if(event->type == InputTypePress) { model->left_pressed = true; - furi_hal_bt_hid_mouse_move(-MOUSE_MOVE_SHORT, 0); + hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_SHORT, 0); } else if(event->type == InputTypeRepeat) { - furi_hal_bt_hid_mouse_move(-MOUSE_MOVE_LONG, 0); + hid_hal_mouse_move(hid_mouse->hid, -MOUSE_MOVE_LONG, 0); } else if(event->type == InputTypeRelease) { model->left_pressed = false; } } else if(event->key == InputKeyDown) { if(event->type == InputTypePress) { model->down_pressed = true; - furi_hal_bt_hid_mouse_move(0, MOUSE_MOVE_SHORT); + hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_SHORT); } else if(event->type == InputTypeRepeat) { - furi_hal_bt_hid_mouse_move(0, MOUSE_MOVE_LONG); + hid_hal_mouse_move(hid_mouse->hid, 0, MOUSE_MOVE_LONG); } else if(event->type == InputTypeRelease) { model->down_pressed = false; } } else if(event->key == InputKeyUp) { if(event->type == InputTypePress) { model->up_pressed = true; - furi_hal_bt_hid_mouse_move(0, -MOUSE_MOVE_SHORT); + hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_SHORT); } else if(event->type == InputTypeRepeat) { - furi_hal_bt_hid_mouse_move(0, -MOUSE_MOVE_LONG); + hid_hal_mouse_move(hid_mouse->hid, 0, -MOUSE_MOVE_LONG); } else if(event->type == InputTypeRelease) { model->up_pressed = false; } @@ -175,45 +174,46 @@ static void bt_hid_mouse_process(BtHidMouse* bt_hid_mouse, InputEvent* event) { true); } -static bool bt_hid_mouse_input_callback(InputEvent* event, void* context) { +static bool hid_mouse_input_callback(InputEvent* event, void* context) { furi_assert(context); - BtHidMouse* bt_hid_mouse = context; + HidMouse* hid_mouse = context; bool consumed = false; if(event->type == InputTypeLong && event->key == InputKeyBack) { - furi_hal_bt_hid_mouse_release_all(); + hid_hal_mouse_release_all(hid_mouse->hid); } else { - bt_hid_mouse_process(bt_hid_mouse, event); + hid_mouse_process(hid_mouse, event); consumed = true; } return consumed; } -BtHidMouse* bt_hid_mouse_alloc() { - BtHidMouse* bt_hid_mouse = malloc(sizeof(BtHidMouse)); - bt_hid_mouse->view = view_alloc(); - view_set_context(bt_hid_mouse->view, bt_hid_mouse); - view_allocate_model(bt_hid_mouse->view, ViewModelTypeLocking, sizeof(BtHidMouseModel)); - view_set_draw_callback(bt_hid_mouse->view, bt_hid_mouse_draw_callback); - view_set_input_callback(bt_hid_mouse->view, bt_hid_mouse_input_callback); +HidMouse* hid_mouse_alloc(Hid* hid) { + HidMouse* hid_mouse = malloc(sizeof(HidMouse)); + hid_mouse->view = view_alloc(); + hid_mouse->hid = hid; + view_set_context(hid_mouse->view, hid_mouse); + view_allocate_model(hid_mouse->view, ViewModelTypeLocking, sizeof(HidMouseModel)); + view_set_draw_callback(hid_mouse->view, hid_mouse_draw_callback); + view_set_input_callback(hid_mouse->view, hid_mouse_input_callback); - return bt_hid_mouse; + return hid_mouse; } -void bt_hid_mouse_free(BtHidMouse* bt_hid_mouse) { - furi_assert(bt_hid_mouse); - view_free(bt_hid_mouse->view); - free(bt_hid_mouse); +void hid_mouse_free(HidMouse* hid_mouse) { + furi_assert(hid_mouse); + view_free(hid_mouse->view); + free(hid_mouse); } -View* bt_hid_mouse_get_view(BtHidMouse* bt_hid_mouse) { - furi_assert(bt_hid_mouse); - return bt_hid_mouse->view; +View* hid_mouse_get_view(HidMouse* hid_mouse) { + furi_assert(hid_mouse); + return hid_mouse->view; } -void bt_hid_mouse_set_connected_status(BtHidMouse* bt_hid_mouse, bool connected) { - furi_assert(bt_hid_mouse); +void hid_mouse_set_connected_status(HidMouse* hid_mouse, bool connected) { + furi_assert(hid_mouse); with_view_model( - bt_hid_mouse->view, BtHidMouseModel * model, { model->connected = connected; }, true); + hid_mouse->view, HidMouseModel * model, { model->connected = connected; }, true); } diff --git a/applications/plugins/hid_app/views/hid_mouse.h b/applications/plugins/hid_app/views/hid_mouse.h new file mode 100644 index 00000000..d9fb2fd8 --- /dev/null +++ b/applications/plugins/hid_app/views/hid_mouse.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#define MOUSE_MOVE_SHORT 5 +#define MOUSE_MOVE_LONG 20 + +typedef struct Hid Hid; +typedef struct HidMouse HidMouse; + +HidMouse* hid_mouse_alloc(Hid* bt_hid); + +void hid_mouse_free(HidMouse* hid_mouse); + +View* hid_mouse_get_view(HidMouse* hid_mouse); + +void hid_mouse_set_connected_status(HidMouse* hid_mouse, bool connected); diff --git a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.c b/applications/plugins/hid_app/views/hid_tiktok.c similarity index 59% rename from applications/plugins/bt_hid_app/views/bt_hid_tiktok.c rename to applications/plugins/hid_app/views/hid_tiktok.c index fe1005b2..42abf414 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_tiktok.c +++ b/applications/plugins/hid_app/views/hid_tiktok.c @@ -1,13 +1,14 @@ -#include "bt_hid_tiktok.h" -#include -#include -#include +#include "hid_tiktok.h" +#include "../hid.h" #include -#include "bt_hid_icons.h" +#include "hid_icons.h" -struct BtHidTikTok { +#define TAG "HidTikTok" + +struct HidTikTok { View* view; + Hid* hid; }; typedef struct { @@ -18,11 +19,11 @@ typedef struct { bool ok_pressed; bool connected; bool is_cursor_set; -} BtHidTikTokModel; +} HidTikTokModel; -static void bt_hid_tiktok_draw_callback(Canvas* canvas, void* context) { +static void hid_tiktok_draw_callback(Canvas* canvas, void* context) { furi_assert(context); - BtHidTikTokModel* model = context; + HidTikTokModel* model = context; // Header if(model->connected) { @@ -89,102 +90,104 @@ static void bt_hid_tiktok_draw_callback(Canvas* canvas, void* context) { elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit"); } -static void bt_hid_tiktok_reset_cursor() { +static void hid_tiktok_reset_cursor(HidTikTok* hid_tiktok) { // Set cursor to the phone's left up corner // Delays to guarantee one packet per connection interval for(size_t i = 0; i < 8; i++) { - furi_hal_bt_hid_mouse_move(-127, -127); + hid_hal_mouse_move(hid_tiktok->hid, -127, -127); furi_delay_ms(50); } // Move cursor from the corner - furi_hal_bt_hid_mouse_move(20, 120); + hid_hal_mouse_move(hid_tiktok->hid, 20, 120); furi_delay_ms(50); } -static void bt_hid_tiktok_process_press(BtHidTikTokModel* model, InputEvent* event) { +static void + hid_tiktok_process_press(HidTikTok* hid_tiktok, HidTikTokModel* model, InputEvent* event) { if(event->key == InputKeyUp) { model->up_pressed = true; } else if(event->key == InputKeyDown) { model->down_pressed = true; } else if(event->key == InputKeyLeft) { model->left_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT); + hid_hal_consumer_key_press(hid_tiktok->hid, HID_CONSUMER_VOLUME_DECREMENT); } else if(event->key == InputKeyRight) { model->right_pressed = true; - furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT); + hid_hal_consumer_key_press(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyOk) { model->ok_pressed = true; } } -static void bt_hid_tiktok_process_release(BtHidTikTokModel* model, InputEvent* event) { +static void + hid_tiktok_process_release(HidTikTok* hid_tiktok, HidTikTokModel* model, InputEvent* event) { if(event->key == InputKeyUp) { model->up_pressed = false; } else if(event->key == InputKeyDown) { model->down_pressed = false; } else if(event->key == InputKeyLeft) { model->left_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT); + hid_hal_consumer_key_release(hid_tiktok->hid, HID_CONSUMER_VOLUME_DECREMENT); } else if(event->key == InputKeyRight) { model->right_pressed = false; - furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT); + hid_hal_consumer_key_release(hid_tiktok->hid, HID_CONSUMER_VOLUME_INCREMENT); } else if(event->key == InputKeyOk) { model->ok_pressed = false; } } -static bool bt_hid_tiktok_input_callback(InputEvent* event, void* context) { +static bool hid_tiktok_input_callback(InputEvent* event, void* context) { furi_assert(context); - BtHidTikTok* bt_hid_tiktok = context; + HidTikTok* hid_tiktok = context; bool consumed = false; with_view_model( - bt_hid_tiktok->view, - BtHidTikTokModel * model, + hid_tiktok->view, + HidTikTokModel * model, { if(event->type == InputTypePress) { - bt_hid_tiktok_process_press(model, event); + hid_tiktok_process_press(hid_tiktok, model, event); if(model->connected && !model->is_cursor_set) { - bt_hid_tiktok_reset_cursor(); + hid_tiktok_reset_cursor(hid_tiktok); model->is_cursor_set = true; } consumed = true; } else if(event->type == InputTypeRelease) { - bt_hid_tiktok_process_release(model, event); + hid_tiktok_process_release(hid_tiktok, model, event); consumed = true; } else if(event->type == InputTypeShort) { if(event->key == InputKeyOk) { - furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); + hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT); furi_delay_ms(50); - furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT); + hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT); furi_delay_ms(50); - furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT); + hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_LEFT); furi_delay_ms(50); - furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT); + hid_hal_mouse_release(hid_tiktok->hid, HID_MOUSE_BTN_LEFT); consumed = true; } else if(event->key == InputKeyUp) { // Emulate up swipe - furi_hal_bt_hid_mouse_scroll(-6); - furi_hal_bt_hid_mouse_scroll(-12); - furi_hal_bt_hid_mouse_scroll(-19); - furi_hal_bt_hid_mouse_scroll(-12); - furi_hal_bt_hid_mouse_scroll(-6); + hid_hal_mouse_scroll(hid_tiktok->hid, -6); + hid_hal_mouse_scroll(hid_tiktok->hid, -12); + hid_hal_mouse_scroll(hid_tiktok->hid, -19); + hid_hal_mouse_scroll(hid_tiktok->hid, -12); + hid_hal_mouse_scroll(hid_tiktok->hid, -6); consumed = true; } else if(event->key == InputKeyDown) { // Emulate down swipe - furi_hal_bt_hid_mouse_scroll(6); - furi_hal_bt_hid_mouse_scroll(12); - furi_hal_bt_hid_mouse_scroll(19); - furi_hal_bt_hid_mouse_scroll(12); - furi_hal_bt_hid_mouse_scroll(6); + hid_hal_mouse_scroll(hid_tiktok->hid, 6); + hid_hal_mouse_scroll(hid_tiktok->hid, 12); + hid_hal_mouse_scroll(hid_tiktok->hid, 19); + hid_hal_mouse_scroll(hid_tiktok->hid, 12); + hid_hal_mouse_scroll(hid_tiktok->hid, 6); consumed = true; } else if(event->key == InputKeyBack) { - furi_hal_bt_hid_consumer_key_release_all(); + hid_hal_consumer_key_release_all(hid_tiktok->hid); consumed = true; } } else if(event->type == InputTypeLong) { if(event->key == InputKeyBack) { - furi_hal_bt_hid_consumer_key_release_all(); + hid_hal_consumer_key_release_all(hid_tiktok->hid); model->is_cursor_set = false; consumed = false; } @@ -195,33 +198,34 @@ static bool bt_hid_tiktok_input_callback(InputEvent* event, void* context) { return consumed; } -BtHidTikTok* bt_hid_tiktok_alloc() { - BtHidTikTok* bt_hid_tiktok = malloc(sizeof(BtHidTikTok)); - bt_hid_tiktok->view = view_alloc(); - view_set_context(bt_hid_tiktok->view, bt_hid_tiktok); - view_allocate_model(bt_hid_tiktok->view, ViewModelTypeLocking, sizeof(BtHidTikTokModel)); - view_set_draw_callback(bt_hid_tiktok->view, bt_hid_tiktok_draw_callback); - view_set_input_callback(bt_hid_tiktok->view, bt_hid_tiktok_input_callback); +HidTikTok* hid_tiktok_alloc(Hid* bt_hid) { + HidTikTok* hid_tiktok = malloc(sizeof(HidTikTok)); + hid_tiktok->hid = bt_hid; + hid_tiktok->view = view_alloc(); + view_set_context(hid_tiktok->view, hid_tiktok); + view_allocate_model(hid_tiktok->view, ViewModelTypeLocking, sizeof(HidTikTokModel)); + view_set_draw_callback(hid_tiktok->view, hid_tiktok_draw_callback); + view_set_input_callback(hid_tiktok->view, hid_tiktok_input_callback); - return bt_hid_tiktok; + return hid_tiktok; } -void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok) { - furi_assert(bt_hid_tiktok); - view_free(bt_hid_tiktok->view); - free(bt_hid_tiktok); +void hid_tiktok_free(HidTikTok* hid_tiktok) { + furi_assert(hid_tiktok); + view_free(hid_tiktok->view); + free(hid_tiktok); } -View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok) { - furi_assert(bt_hid_tiktok); - return bt_hid_tiktok->view; +View* hid_tiktok_get_view(HidTikTok* hid_tiktok) { + furi_assert(hid_tiktok); + return hid_tiktok->view; } -void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected) { - furi_assert(bt_hid_tiktok); +void hid_tiktok_set_connected_status(HidTikTok* hid_tiktok, bool connected) { + furi_assert(hid_tiktok); with_view_model( - bt_hid_tiktok->view, - BtHidTikTokModel * model, + hid_tiktok->view, + HidTikTokModel * model, { model->connected = connected; model->is_cursor_set = false; diff --git a/applications/plugins/hid_app/views/hid_tiktok.h b/applications/plugins/hid_app/views/hid_tiktok.h new file mode 100644 index 00000000..b2efc369 --- /dev/null +++ b/applications/plugins/hid_app/views/hid_tiktok.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct Hid Hid; +typedef struct HidTikTok HidTikTok; + +HidTikTok* hid_tiktok_alloc(Hid* bt_hid); + +void hid_tiktok_free(HidTikTok* hid_tiktok); + +View* hid_tiktok_get_view(HidTikTok* hid_tiktok); + +void hid_tiktok_set_connected_status(HidTikTok* hid_tiktok, bool connected); diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 908a64a6..a7460d88 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -64,6 +64,7 @@ class FlipperApplication: fap_author: str = "" fap_weburl: str = "" fap_icon_assets: Optional[str] = None + fap_icon_assets_symbol: Optional[str] = None fap_extbuild: List[ExternallyBuiltFile] = field(default_factory=list) fap_private_libs: List[Library] = field(default_factory=list) # Internally used by fbt diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index a4116e51..f0015cf2 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -60,7 +60,7 @@ def BuildAppElf(env, app): fap_icons = app_env.CompileIcons( app_env.Dir(app_work_dir), app._appdir.Dir(app.fap_icon_assets), - icon_bundle_name=f"{app.appid}_icons", + icon_bundle_name=f"{app.fap_icon_assets_symbol if app.fap_icon_assets_symbol else app.appid }_icons", ) app_env.Alias("_fap_icons", fap_icons)