Add missing buttons into hid app, remove old app
Now its all in one app, compiles as two apps that will be placed in misc folder
No files matched your search
@@ -116,7 +116,6 @@ You can support us by using links or addresses below:
|
||||
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
|
||||
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
|
||||
- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
|
||||
- USB Keyboard plugin [(by huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard)
|
||||
- WAV Player [(OFW: DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) - Fixed and improved by [LTVA1](https://github.com/LTVA1/wav_player)
|
||||
- Barcode generator plugin [(original by McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) - [EAN-8 and refactoring](https://github.com/DarkFlippers/unleashed-firmware/pull/154) by @msvsergey
|
||||
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#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_usb",
|
||||
name="USB Keyboard & Mouse",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="hid_usb_app",
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Misc",
|
||||
fap_icon="hid_usb_10px.png",
|
||||
fap_icon_assets="assets",
|
||||
fap_icon_assets_symbol="hid",
|
||||
)
|
||||
|
||||
|
||||
App(
|
||||
@@ -17,7 +17,7 @@ App(
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="hid_ble_app",
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Tools",
|
||||
fap_category="Misc",
|
||||
fap_icon="hid_ble_10px.png",
|
||||
fap_icon_assets="assets",
|
||||
fap_icon_assets_symbol="hid",
|
||||
|
||||
|
Before Width: | Height: | Size: 969 B After Width: | Height: | Size: 174 B |
@@ -140,18 +140,18 @@ const HidKeyboardKey hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
|
||||
{.width = 1, .icon = &I_ButtonRight_4x7, .value = HID_KEYBOARD_RIGHT_ARROW},
|
||||
},
|
||||
{
|
||||
{.width = 3, .icon = NULL, .key = "Ctrl", .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 2, .icon = NULL, .key = "Ctl", .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 3, .icon = NULL, .key = "Alt", .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 2, .icon = NULL, .key = "Alt", .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 3, .icon = NULL, .key = "Cmd", .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 2, .icon = NULL, .key = "Cmd", .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 3, .icon = NULL, .key = "Tab", .value = HID_KEYBOARD_TAB},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_TAB},
|
||||
{.width = 2, .icon = NULL, .key = "Tab", .value = HID_KEYBOARD_TAB},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_TAB},
|
||||
{.width = 2, .icon = NULL, .key = "Esc", .value = HID_KEYBOARD_ESCAPE},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_ESCAPE},
|
||||
{.width = 2, .icon = NULL, .key = "Del", .value = HID_KEYBOARD_DELETE_FORWARD},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_DELETE_FORWARD},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2022, Gabriel Cirlig
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,15 +0,0 @@
|
||||
App(
|
||||
appid="USB_Keyboard",
|
||||
name="USB Keyboard & Mouse",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
entry_point="usb_hid_app",
|
||||
stack_size=1 * 1024,
|
||||
cdefines=["APP_USB_KEYBOARD"],
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
order=60,
|
||||
fap_icon="usb_keyboard_10px.png",
|
||||
fap_category="Misc",
|
||||
fap_icon_assets="assets",
|
||||
)
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 102 B |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1,198 +0,0 @@
|
||||
#include "usb_hid.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define TAG "UsbHidApp"
|
||||
|
||||
enum UsbDebugSubmenuIndex {
|
||||
UsbHidSubmenuIndexDirpad,
|
||||
UsbHidSubmenuIndexKeyboard,
|
||||
UsbHidSubmenuIndexMedia,
|
||||
UsbHidSubmenuIndexMouse,
|
||||
UsbHidSubmenuIndexMouseJiggler,
|
||||
};
|
||||
|
||||
void usb_hid_submenu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
UsbHid* app = context;
|
||||
if(index == UsbHidSubmenuIndexDirpad) {
|
||||
app->view_id = UsbHidViewDirpad;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewDirpad);
|
||||
} else if(index == UsbHidSubmenuIndexKeyboard) {
|
||||
app->view_id = UsbHidViewKeyboard;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewKeyboard);
|
||||
} else if(index == UsbHidSubmenuIndexMedia) {
|
||||
app->view_id = UsbHidViewMedia;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewMedia);
|
||||
} else if(index == UsbHidSubmenuIndexMouse) {
|
||||
app->view_id = UsbHidViewMouse;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewMouse);
|
||||
} else if(index == UsbHidSubmenuIndexMouseJiggler) {
|
||||
app->view_id = UsbHidViewMouseJiggler;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewMouseJiggler);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_hid_dialog_callback(DialogExResult result, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHid* 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, UsbHidViewSubmenu);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t usb_hid_exit_confirm_view(void* context) {
|
||||
UNUSED(context);
|
||||
return UsbHidViewExitConfirm;
|
||||
}
|
||||
|
||||
uint32_t usb_hid_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
UsbHid* usb_hid_app_alloc() {
|
||||
UsbHid* app = malloc(sizeof(UsbHid));
|
||||
|
||||
// Gui
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
// 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, "Dirpad", UsbHidSubmenuIndexDirpad, usb_hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Keyboard", UsbHidSubmenuIndexKeyboard, usb_hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Media", UsbHidSubmenuIndexMedia, usb_hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu, "Mouse", UsbHidSubmenuIndexMouse, usb_hid_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Mouse Jiggler",
|
||||
UsbHidSubmenuIndexMouseJiggler,
|
||||
usb_hid_submenu_callback,
|
||||
app);
|
||||
view_set_previous_callback(submenu_get_view(app->submenu), usb_hid_exit);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, UsbHidViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
// Dialog view
|
||||
app->dialog = dialog_ex_alloc();
|
||||
dialog_ex_set_result_callback(app->dialog, usb_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, UsbHidViewExitConfirm, dialog_ex_get_view(app->dialog));
|
||||
|
||||
// Dirpad view
|
||||
app->usb_hid_dirpad = usb_hid_dirpad_alloc();
|
||||
view_set_previous_callback(
|
||||
usb_hid_dirpad_get_view(app->usb_hid_dirpad), usb_hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, UsbHidViewDirpad, usb_hid_dirpad_get_view(app->usb_hid_dirpad));
|
||||
|
||||
// Keyboard view
|
||||
app->usb_hid_keyboard = usb_hid_keyboard_alloc();
|
||||
view_set_previous_callback(
|
||||
usb_hid_keyboard_get_view(app->usb_hid_keyboard), usb_hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
UsbHidViewKeyboard,
|
||||
usb_hid_keyboard_get_view(app->usb_hid_keyboard));
|
||||
|
||||
// Media view
|
||||
app->usb_hid_media = usb_hid_media_alloc();
|
||||
view_set_previous_callback(
|
||||
usb_hid_media_get_view(app->usb_hid_media), usb_hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, UsbHidViewMedia, usb_hid_media_get_view(app->usb_hid_media));
|
||||
|
||||
// Mouse view
|
||||
app->usb_hid_mouse = usb_hid_mouse_alloc();
|
||||
view_set_previous_callback(
|
||||
usb_hid_mouse_get_view(app->usb_hid_mouse), usb_hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, UsbHidViewMouse, usb_hid_mouse_get_view(app->usb_hid_mouse));
|
||||
|
||||
// Mouse jiggler view
|
||||
app->hid_mouse_jiggler = hid_mouse_jiggler_alloc(app);
|
||||
view_set_previous_callback(
|
||||
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler), usb_hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
UsbHidViewMouseJiggler,
|
||||
hid_mouse_jiggler_get_view(app->hid_mouse_jiggler));
|
||||
|
||||
// TODO switch to menu after Media is done
|
||||
app->view_id = UsbHidViewSubmenu;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
void usb_hid_app_free(UsbHid* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Reset notification
|
||||
notification_internal_message(app->notifications, &sequence_reset_blue);
|
||||
|
||||
// Free views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewSubmenu);
|
||||
submenu_free(app->submenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewExitConfirm);
|
||||
dialog_ex_free(app->dialog);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewDirpad);
|
||||
usb_hid_dirpad_free(app->usb_hid_dirpad);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewKeyboard);
|
||||
usb_hid_keyboard_free(app->usb_hid_keyboard);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewMedia);
|
||||
usb_hid_media_free(app->usb_hid_media);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewMouse);
|
||||
usb_hid_mouse_free(app->usb_hid_mouse);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewMouseJiggler);
|
||||
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
// Close records
|
||||
furi_record_close(RECORD_GUI);
|
||||
app->gui = NULL;
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
app->notifications = NULL;
|
||||
|
||||
// Free rest
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t usb_hid_app(void* p) {
|
||||
UNUSED(p);
|
||||
// Switch profile to Hid
|
||||
UsbHid* app = usb_hid_app_alloc();
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
// Change back profile
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
usb_hid_app_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <notification/notification.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
#include "views/usb_hid_dirpad.h"
|
||||
#include "views/usb_hid_keyboard.h"
|
||||
#include "views/usb_hid_media.h"
|
||||
#include "views/usb_hid_mouse.h"
|
||||
#include "views/usb_hid_mouse_jiggler.h"
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
DialogEx* dialog;
|
||||
UsbHidDirpad* usb_hid_dirpad;
|
||||
UsbHidKeyboard* usb_hid_keyboard;
|
||||
UsbHidMedia* usb_hid_media;
|
||||
UsbHidMouse* usb_hid_mouse;
|
||||
HidMouseJiggler* hid_mouse_jiggler;
|
||||
uint32_t view_id;
|
||||
} UsbHid;
|
||||
|
||||
typedef enum {
|
||||
UsbHidViewSubmenu,
|
||||
UsbHidViewDirpad,
|
||||
UsbHidViewKeyboard,
|
||||
UsbHidViewMedia,
|
||||
UsbHidViewMouse,
|
||||
UsbHidViewMouseJiggler,
|
||||
UsbHidViewExitConfirm,
|
||||
} UsbHidView;
|
||||
|
Before Width: | Height: | Size: 174 B |
@@ -1,197 +0,0 @@
|
||||
#include "usb_hid_dirpad.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <gui/elements.h>
|
||||
#include <USB_Keyboard_icons.h>
|
||||
|
||||
struct UsbHidDirpad {
|
||||
View* view;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool left_pressed;
|
||||
bool up_pressed;
|
||||
bool right_pressed;
|
||||
bool down_pressed;
|
||||
bool ok_pressed;
|
||||
bool back_pressed;
|
||||
bool connected;
|
||||
} UsbHidDirpadModel;
|
||||
|
||||
static void usb_hid_dirpad_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);
|
||||
} else if(dir == CanvasDirectionTopToBottom) {
|
||||
canvas_draw_line(canvas, x, y - 6, x, y + 1);
|
||||
} else if(dir == CanvasDirectionRightToLeft) {
|
||||
canvas_draw_line(canvas, x + 6, y, x - 1, y);
|
||||
} else if(dir == CanvasDirectionLeftToRight) {
|
||||
canvas_draw_line(canvas, x - 6, y, x + 1, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_hid_dirpad_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidDirpadModel* model = context;
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Dirpad");
|
||||
|
||||
canvas_draw_icon(canvas, 68, 2, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 127, 3, AlignRight, AlignTop, "Hold to exit");
|
||||
|
||||
// Up
|
||||
canvas_draw_icon(canvas, 21, 24, &I_Button_18x18);
|
||||
if(model->up_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 24, 26, 13, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_dirpad_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Down
|
||||
canvas_draw_icon(canvas, 21, 45, &I_Button_18x18);
|
||||
if(model->down_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 24, 47, 13, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_dirpad_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Left
|
||||
canvas_draw_icon(canvas, 0, 45, &I_Button_18x18);
|
||||
if(model->left_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 3, 47, 13, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_dirpad_draw_arrow(canvas, 7, 53, CanvasDirectionRightToLeft);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Right
|
||||
canvas_draw_icon(canvas, 42, 45, &I_Button_18x18);
|
||||
if(model->right_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 45, 47, 13, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_dirpad_draw_arrow(canvas, 53, 53, CanvasDirectionLeftToRight);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Ok
|
||||
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18);
|
||||
if(model->ok_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 66, 27, 60, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9);
|
||||
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "Space");
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Back
|
||||
canvas_draw_icon(canvas, 63, 45, &I_Space_65x18);
|
||||
if(model->back_pressed) {
|
||||
elements_slightly_rounded_box(canvas, 66, 47, 60, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8);
|
||||
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "Back");
|
||||
}
|
||||
|
||||
static void usb_hid_dirpad_process(UsbHidDirpad* usb_hid_dirpad, InputEvent* event) {
|
||||
with_view_model(
|
||||
usb_hid_dirpad->view,
|
||||
UsbHidDirpadModel * model,
|
||||
{
|
||||
if(event->type == InputTypePress) {
|
||||
if(event->key == InputKeyUp) {
|
||||
model->up_pressed = true;
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_UP_ARROW);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = true;
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_DOWN_ARROW);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = true;
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_LEFT_ARROW);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = true;
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_RIGHT_ARROW);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = true;
|
||||
furi_hal_hid_kb_press(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_hid_kb_release(HID_KEYBOARD_UP_ARROW);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = false;
|
||||
furi_hal_hid_kb_release(HID_KEYBOARD_DOWN_ARROW);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = false;
|
||||
furi_hal_hid_kb_release(HID_KEYBOARD_LEFT_ARROW);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = false;
|
||||
furi_hal_hid_kb_release(HID_KEYBOARD_RIGHT_ARROW);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = false;
|
||||
furi_hal_hid_kb_release(HID_KEYBOARD_SPACEBAR);
|
||||
} else if(event->key == InputKeyBack) {
|
||||
model->back_pressed = false;
|
||||
}
|
||||
} else if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyBack) {
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_DELETE);
|
||||
furi_hal_hid_kb_release(HID_KEYBOARD_DELETE);
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_AC_BACK);
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_AC_BACK);
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static bool usb_hid_dirpad_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidDirpad* usb_hid_dirpad = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeLong && event->key == InputKeyBack) {
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else {
|
||||
usb_hid_dirpad_process(usb_hid_dirpad, event);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
UsbHidDirpad* usb_hid_dirpad_alloc() {
|
||||
UsbHidDirpad* usb_hid_dirpad = malloc(sizeof(UsbHidDirpad));
|
||||
usb_hid_dirpad->view = view_alloc();
|
||||
view_set_context(usb_hid_dirpad->view, usb_hid_dirpad);
|
||||
view_allocate_model(usb_hid_dirpad->view, ViewModelTypeLocking, sizeof(UsbHidDirpadModel));
|
||||
view_set_draw_callback(usb_hid_dirpad->view, usb_hid_dirpad_draw_callback);
|
||||
view_set_input_callback(usb_hid_dirpad->view, usb_hid_dirpad_input_callback);
|
||||
|
||||
return usb_hid_dirpad;
|
||||
}
|
||||
|
||||
void usb_hid_dirpad_free(UsbHidDirpad* usb_hid_dirpad) {
|
||||
furi_assert(usb_hid_dirpad);
|
||||
view_free(usb_hid_dirpad->view);
|
||||
free(usb_hid_dirpad);
|
||||
}
|
||||
|
||||
View* usb_hid_dirpad_get_view(UsbHidDirpad* usb_hid_dirpad) {
|
||||
furi_assert(usb_hid_dirpad);
|
||||
return usb_hid_dirpad->view;
|
||||
}
|
||||
|
||||
void usb_hid_dirpad_set_connected_status(UsbHidDirpad* usb_hid_dirpad, bool connected) {
|
||||
furi_assert(usb_hid_dirpad);
|
||||
with_view_model(
|
||||
usb_hid_dirpad->view, UsbHidDirpadModel * model, { model->connected = connected; }, true);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct UsbHidDirpad UsbHidDirpad;
|
||||
|
||||
UsbHidDirpad* usb_hid_dirpad_alloc();
|
||||
|
||||
void usb_hid_dirpad_free(UsbHidDirpad* usb_hid_dirpad);
|
||||
|
||||
View* usb_hid_dirpad_get_view(UsbHidDirpad* usb_hid_dirpad);
|
||||
|
||||
void usb_hid_dirpad_set_connected_status(UsbHidDirpad* usb_hid_dirpad, bool connected);
|
||||
@@ -1,387 +0,0 @@
|
||||
#include "usb_hid_keyboard.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/icon_i.h>
|
||||
#include <USB_Keyboard_icons.h>
|
||||
|
||||
struct UsbHidKeyboard {
|
||||
View* view;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool shift;
|
||||
bool alt;
|
||||
bool ctrl;
|
||||
bool gui;
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t last_key_code;
|
||||
uint16_t modifier_code;
|
||||
bool ok_pressed;
|
||||
bool back_pressed;
|
||||
bool connected;
|
||||
char key_string[5];
|
||||
} UsbHidKeyboardModel;
|
||||
|
||||
typedef struct {
|
||||
uint8_t width;
|
||||
char* key;
|
||||
const Icon* icon;
|
||||
char* shift_key;
|
||||
uint8_t value;
|
||||
} UsbHidKeyboardKey;
|
||||
|
||||
typedef struct {
|
||||
int8_t x;
|
||||
int8_t y;
|
||||
} UsbHidKeyboardPoint;
|
||||
|
||||
// 4 BY 12
|
||||
#define MARGIN_TOP 0
|
||||
#define MARGIN_LEFT 4
|
||||
#define KEY_WIDTH 9
|
||||
#define KEY_HEIGHT 12
|
||||
#define KEY_PADDING 1
|
||||
#define ROW_COUNT 7
|
||||
#define COLUMN_COUNT 12
|
||||
|
||||
// 0 width items are not drawn, but there value is used
|
||||
const UsbHidKeyboardKey usb_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},
|
||||
{.width = 1, .icon = NULL, .key = "3", .shift_key = "#", .value = HID_KEYBOARD_3},
|
||||
{.width = 1, .icon = NULL, .key = "4", .shift_key = "$", .value = HID_KEYBOARD_4},
|
||||
{.width = 1, .icon = NULL, .key = "5", .shift_key = "%", .value = HID_KEYBOARD_5},
|
||||
{.width = 1, .icon = NULL, .key = "6", .shift_key = "^", .value = HID_KEYBOARD_6},
|
||||
{.width = 1, .icon = NULL, .key = "7", .shift_key = "&", .value = HID_KEYBOARD_7},
|
||||
{.width = 1, .icon = NULL, .key = "8", .shift_key = "*", .value = HID_KEYBOARD_8},
|
||||
{.width = 1, .icon = NULL, .key = "9", .shift_key = "(", .value = HID_KEYBOARD_9},
|
||||
{.width = 1, .icon = NULL, .key = "0", .shift_key = ")", .value = HID_KEYBOARD_0},
|
||||
{.width = 2, .icon = &I_Pin_arrow_left_9x7, .value = HID_KEYBOARD_DELETE},
|
||||
{.width = 0, .value = HID_KEYBOARD_DELETE},
|
||||
},
|
||||
{
|
||||
{.width = 1, .icon = NULL, .key = "q", .shift_key = "Q", .value = HID_KEYBOARD_Q},
|
||||
{.width = 1, .icon = NULL, .key = "w", .shift_key = "W", .value = HID_KEYBOARD_W},
|
||||
{.width = 1, .icon = NULL, .key = "e", .shift_key = "E", .value = HID_KEYBOARD_E},
|
||||
{.width = 1, .icon = NULL, .key = "r", .shift_key = "R", .value = HID_KEYBOARD_R},
|
||||
{.width = 1, .icon = NULL, .key = "t", .shift_key = "T", .value = HID_KEYBOARD_T},
|
||||
{.width = 1, .icon = NULL, .key = "y", .shift_key = "Y", .value = HID_KEYBOARD_Y},
|
||||
{.width = 1, .icon = NULL, .key = "u", .shift_key = "U", .value = HID_KEYBOARD_U},
|
||||
{.width = 1, .icon = NULL, .key = "i", .shift_key = "I", .value = HID_KEYBOARD_I},
|
||||
{.width = 1, .icon = NULL, .key = "o", .shift_key = "O", .value = HID_KEYBOARD_O},
|
||||
{.width = 1, .icon = NULL, .key = "p", .shift_key = "P", .value = HID_KEYBOARD_P},
|
||||
{.width = 1, .icon = NULL, .key = "[", .shift_key = "{", .value = HID_KEYBOARD_OPEN_BRACKET},
|
||||
{.width = 1,
|
||||
.icon = NULL,
|
||||
.key = "]",
|
||||
.shift_key = "}",
|
||||
.value = HID_KEYBOARD_CLOSE_BRACKET},
|
||||
},
|
||||
{
|
||||
{.width = 1, .icon = NULL, .key = "a", .shift_key = "A", .value = HID_KEYBOARD_A},
|
||||
{.width = 1, .icon = NULL, .key = "s", .shift_key = "S", .value = HID_KEYBOARD_S},
|
||||
{.width = 1, .icon = NULL, .key = "d", .shift_key = "D", .value = HID_KEYBOARD_D},
|
||||
{.width = 1, .icon = NULL, .key = "f", .shift_key = "F", .value = HID_KEYBOARD_F},
|
||||
{.width = 1, .icon = NULL, .key = "g", .shift_key = "G", .value = HID_KEYBOARD_G},
|
||||
{.width = 1, .icon = NULL, .key = "h", .shift_key = "H", .value = HID_KEYBOARD_H},
|
||||
{.width = 1, .icon = NULL, .key = "j", .shift_key = "J", .value = HID_KEYBOARD_J},
|
||||
{.width = 1, .icon = NULL, .key = "k", .shift_key = "K", .value = HID_KEYBOARD_K},
|
||||
{.width = 1, .icon = NULL, .key = "l", .shift_key = "L", .value = HID_KEYBOARD_L},
|
||||
{.width = 1, .icon = NULL, .key = ";", .shift_key = ":", .value = HID_KEYBOARD_SEMICOLON},
|
||||
{.width = 2, .icon = &I_Pin_arrow_right_9x7, .value = HID_KEYBOARD_RETURN},
|
||||
{.width = 0, .value = HID_KEYBOARD_RETURN},
|
||||
},
|
||||
{
|
||||
{.width = 1, .icon = NULL, .key = "z", .shift_key = "Z", .value = HID_KEYBOARD_Z},
|
||||
{.width = 1, .icon = NULL, .key = "x", .shift_key = "X", .value = HID_KEYBOARD_X},
|
||||
{.width = 1, .icon = NULL, .key = "c", .shift_key = "C", .value = HID_KEYBOARD_C},
|
||||
{.width = 1, .icon = NULL, .key = "v", .shift_key = "V", .value = HID_KEYBOARD_V},
|
||||
{.width = 1, .icon = NULL, .key = "b", .shift_key = "B", .value = HID_KEYBOARD_B},
|
||||
{.width = 1, .icon = NULL, .key = "n", .shift_key = "N", .value = HID_KEYBOARD_N},
|
||||
{.width = 1, .icon = NULL, .key = "m", .shift_key = "M", .value = HID_KEYBOARD_M},
|
||||
{.width = 1, .icon = NULL, .key = "/", .shift_key = "?", .value = HID_KEYBOARD_SLASH},
|
||||
{.width = 1, .icon = NULL, .key = "\\", .shift_key = "|", .value = HID_KEYBOARD_BACKSLASH},
|
||||
{.width = 1, .icon = NULL, .key = "`", .shift_key = "~", .value = HID_KEYBOARD_GRAVE_ACCENT},
|
||||
{.width = 1, .icon = &I_ButtonUp_7x4, .value = HID_KEYBOARD_UP_ARROW},
|
||||
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
|
||||
},
|
||||
{
|
||||
{.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_DOT},
|
||||
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},
|
||||
{.width = 0, .value = HID_KEYBOARD_SPACEBAR},
|
||||
{.width = 0, .value = HID_KEYBOARD_SPACEBAR},
|
||||
{.width = 0, .value = HID_KEYBOARD_SPACEBAR},
|
||||
{.width = 1, .icon = NULL, .key = "'", .shift_key = "\"", .value = HID_KEYBOARD_APOSTROPHE},
|
||||
{.width = 1, .icon = NULL, .key = "=", .shift_key = "+", .value = HID_KEYBOARD_EQUAL_SIGN},
|
||||
{.width = 1, .icon = &I_ButtonLeft_4x7, .value = HID_KEYBOARD_LEFT_ARROW},
|
||||
{.width = 1, .icon = &I_ButtonDown_7x4, .value = HID_KEYBOARD_DOWN_ARROW},
|
||||
{.width = 1, .icon = &I_ButtonRight_4x7, .value = HID_KEYBOARD_RIGHT_ARROW},
|
||||
},
|
||||
{
|
||||
{.width = 2, .icon = NULL, .key = "Ctl", .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_CTRL},
|
||||
{.width = 2, .icon = NULL, .key = "Alt", .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_ALT},
|
||||
{.width = 2, .icon = NULL, .key = "Cmd", .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_L_GUI},
|
||||
{.width = 2, .icon = NULL, .key = "Tab", .value = HID_KEYBOARD_TAB},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_TAB},
|
||||
{.width = 2, .icon = NULL, .key = "Esc", .value = HID_KEYBOARD_ESCAPE},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_ESCAPE},
|
||||
{.width = 2, .icon = NULL, .key = "Del", .value = HID_KEYBOARD_DELETE_FORWARD},
|
||||
{.width = 0, .icon = NULL, .value = HID_KEYBOARD_DELETE_FORWARD},
|
||||
},
|
||||
{
|
||||
{.width = 1, .icon = NULL, .key = "1", .shift_key = "1", .value = HID_KEYBOARD_F1},
|
||||
{.width = 1, .icon = NULL, .key = "2", .shift_key = "2", .value = HID_KEYBOARD_F2},
|
||||
{.width = 1, .icon = NULL, .key = "3", .shift_key = "3", .value = HID_KEYBOARD_F3},
|
||||
{.width = 1, .icon = NULL, .key = "4", .shift_key = "4", .value = HID_KEYBOARD_F4},
|
||||
{.width = 1, .icon = NULL, .key = "5", .shift_key = "5", .value = HID_KEYBOARD_F5},
|
||||
{.width = 1, .icon = NULL, .key = "6", .shift_key = "6", .value = HID_KEYBOARD_F6},
|
||||
{.width = 1, .icon = NULL, .key = "7", .shift_key = "7", .value = HID_KEYBOARD_F7},
|
||||
{.width = 1, .icon = NULL, .key = "8", .shift_key = "8", .value = HID_KEYBOARD_F8},
|
||||
{.width = 1, .icon = NULL, .key = "9", .shift_key = "9", .value = HID_KEYBOARD_F9},
|
||||
{.width = 1, .icon = NULL, .key = "0", .shift_key = "0", .value = HID_KEYBOARD_F10},
|
||||
{.width = 1, .icon = NULL, .key = "1", .shift_key = "1", .value = HID_KEYBOARD_F11},
|
||||
{.width = 1, .icon = NULL, .key = "2", .shift_key = "2", .value = HID_KEYBOARD_F12},
|
||||
}};
|
||||
|
||||
static void usb_hid_keyboard_to_upper(char* str) {
|
||||
while(*str) {
|
||||
*str = toupper((unsigned char)*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_hid_keyboard_draw_key(
|
||||
Canvas* canvas,
|
||||
UsbHidKeyboardModel* model,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
UsbHidKeyboardKey key,
|
||||
bool selected) {
|
||||
if(!key.width) return;
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
uint8_t keyWidth = KEY_WIDTH * key.width + KEY_PADDING * (key.width - 1);
|
||||
if(selected) {
|
||||
// Draw a filled box
|
||||
elements_slightly_rounded_box(
|
||||
canvas,
|
||||
MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING),
|
||||
MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING),
|
||||
keyWidth,
|
||||
KEY_HEIGHT);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
} else {
|
||||
// Draw a framed box
|
||||
elements_slightly_rounded_frame(
|
||||
canvas,
|
||||
MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING),
|
||||
MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING),
|
||||
keyWidth,
|
||||
KEY_HEIGHT);
|
||||
}
|
||||
if(key.icon != NULL) {
|
||||
// Draw the icon centered on the button
|
||||
canvas_draw_icon(
|
||||
canvas,
|
||||
MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 - key.icon->width / 2,
|
||||
MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + KEY_HEIGHT / 2 - key.icon->height / 2,
|
||||
key.icon);
|
||||
} else {
|
||||
// If shift is toggled use the shift key when available
|
||||
strcpy(model->key_string, (model->shift && key.shift_key != 0) ? key.shift_key : key.key);
|
||||
// Upper case if ctrl or alt was toggled true
|
||||
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)) {
|
||||
usb_hid_keyboard_to_upper(model->key_string);
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
MARGIN_LEFT + x * (KEY_WIDTH + KEY_PADDING) + keyWidth / 2 + 1,
|
||||
MARGIN_TOP + y * (KEY_HEIGHT + KEY_PADDING) + KEY_HEIGHT / 2,
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
model->key_string);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_hid_keyboard_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidKeyboardModel* model = context;
|
||||
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
// 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 UsbHidKeyboardKey* keyboardKeyRow = usb_hid_keyboard_keyset[y];
|
||||
uint8_t x = 0;
|
||||
for(uint8_t i = 0; i < COLUMN_COUNT; i++) {
|
||||
UsbHidKeyboardKey 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;
|
||||
// Revert selection for function keys
|
||||
keySelected = y == ROW_COUNT - 1 ? !keySelected : keySelected;
|
||||
bool backSelected = model->back_pressed && key.value == HID_KEYBOARD_DELETE;
|
||||
usb_hid_keyboard_draw_key(
|
||||
canvas,
|
||||
model,
|
||||
x,
|
||||
y - initY,
|
||||
key,
|
||||
(!model->ok_pressed && keySelected) || backSelected);
|
||||
x += key.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t usb_hid_keyboard_get_selected_key(UsbHidKeyboardModel* model) {
|
||||
UsbHidKeyboardKey key = usb_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
|
||||
bool hasUppercase = key.shift_key != 0;
|
||||
if(useUppercase && hasUppercase)
|
||||
return key.value;
|
||||
else
|
||||
return key.value;
|
||||
}
|
||||
|
||||
static void
|
||||
usb_hid_keyboard_get_select_key(UsbHidKeyboardModel* model, UsbHidKeyboardPoint 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 && usb_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 && usb_hid_keyboard_keyset[model->y][model->x].width ==
|
||||
0); // Skip zero width keys, pretend they are one key
|
||||
}
|
||||
|
||||
static void usb_hid_keyboard_process(UsbHidKeyboard* usb_hid_keyboard, InputEvent* event) {
|
||||
with_view_model(
|
||||
usb_hid_keyboard->view,
|
||||
UsbHidKeyboardModel * 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 = usb_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) {
|
||||
model->shift = !model->shift;
|
||||
if(model->shift)
|
||||
model->modifier_code |= KEY_MOD_LEFT_SHIFT;
|
||||
else
|
||||
model->modifier_code &= ~KEY_MOD_LEFT_SHIFT;
|
||||
} else if(model->last_key_code == HID_KEYBOARD_L_ALT) {
|
||||
model->alt = !model->alt;
|
||||
if(model->alt)
|
||||
model->modifier_code |= KEY_MOD_LEFT_ALT;
|
||||
else
|
||||
model->modifier_code &= ~KEY_MOD_LEFT_ALT;
|
||||
} else if(model->last_key_code == HID_KEYBOARD_L_CTRL) {
|
||||
model->ctrl = !model->ctrl;
|
||||
if(model->ctrl)
|
||||
model->modifier_code |= KEY_MOD_LEFT_CTRL;
|
||||
else
|
||||
model->modifier_code &= ~KEY_MOD_LEFT_CTRL;
|
||||
} else if(model->last_key_code == HID_KEYBOARD_L_GUI) {
|
||||
model->gui = !model->gui;
|
||||
if(model->gui)
|
||||
model->modifier_code |= KEY_MOD_LEFT_GUI;
|
||||
else
|
||||
model->modifier_code &= ~KEY_MOD_LEFT_GUI;
|
||||
}
|
||||
furi_hal_hid_kb_press(model->modifier_code | model->last_key_code);
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
// Release happens after short and long presses
|
||||
furi_hal_hid_kb_release(model->modifier_code | model->last_key_code);
|
||||
model->ok_pressed = false;
|
||||
}
|
||||
} else if(event->key == InputKeyBack) {
|
||||
// If back is pressed for a short time, backspace
|
||||
if(event->type == InputTypePress) {
|
||||
model->back_pressed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
furi_hal_hid_kb_press(HID_KEYBOARD_DELETE);
|
||||
furi_hal_hid_kb_release(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) {
|
||||
usb_hid_keyboard_get_select_key(model, (UsbHidKeyboardPoint){.x = 0, .y = -1});
|
||||
} else if(event->key == InputKeyDown) {
|
||||
usb_hid_keyboard_get_select_key(model, (UsbHidKeyboardPoint){.x = 0, .y = 1});
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
usb_hid_keyboard_get_select_key(model, (UsbHidKeyboardPoint){.x = -1, .y = 0});
|
||||
} else if(event->key == InputKeyRight) {
|
||||
usb_hid_keyboard_get_select_key(model, (UsbHidKeyboardPoint){.x = 1, .y = 0});
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static bool usb_hid_keyboard_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidKeyboard* usb_hid_keyboard = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeLong && event->key == InputKeyBack) {
|
||||
furi_hal_hid_kb_release_all();
|
||||
} else {
|
||||
usb_hid_keyboard_process(usb_hid_keyboard, event);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
UsbHidKeyboard* usb_hid_keyboard_alloc() {
|
||||
UsbHidKeyboard* usb_hid_keyboard = malloc(sizeof(UsbHidKeyboard));
|
||||
|
||||
usb_hid_keyboard->view = view_alloc();
|
||||
view_set_context(usb_hid_keyboard->view, usb_hid_keyboard);
|
||||
view_allocate_model(usb_hid_keyboard->view, ViewModelTypeLocking, sizeof(UsbHidKeyboardModel));
|
||||
view_set_draw_callback(usb_hid_keyboard->view, usb_hid_keyboard_draw_callback);
|
||||
view_set_input_callback(usb_hid_keyboard->view, usb_hid_keyboard_input_callback);
|
||||
|
||||
with_view_model(
|
||||
usb_hid_keyboard->view, UsbHidKeyboardModel * model, { model->connected = true; }, true);
|
||||
|
||||
return usb_hid_keyboard;
|
||||
}
|
||||
|
||||
void usb_hid_keyboard_free(UsbHidKeyboard* usb_hid_keyboard) {
|
||||
furi_assert(usb_hid_keyboard);
|
||||
view_free(usb_hid_keyboard->view);
|
||||
free(usb_hid_keyboard);
|
||||
}
|
||||
|
||||
View* usb_hid_keyboard_get_view(UsbHidKeyboard* usb_hid_keyboard) {
|
||||
furi_assert(usb_hid_keyboard);
|
||||
return usb_hid_keyboard->view;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct UsbHidKeyboard UsbHidKeyboard;
|
||||
|
||||
UsbHidKeyboard* usb_hid_keyboard_alloc();
|
||||
|
||||
void usb_hid_keyboard_free(UsbHidKeyboard* usb_hid_keyboard);
|
||||
|
||||
View* usb_hid_keyboard_get_view(UsbHidKeyboard* usb_hid_keyboard);
|
||||
|
||||
void usb_hid_keyboard_set_connected_status(UsbHidKeyboard* usb_hid_keyboard, bool connected);
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "usb_hid_media.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <gui/elements.h>
|
||||
#include <USB_Keyboard_icons.h>
|
||||
|
||||
struct UsbHidMedia {
|
||||
View* view;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool left_pressed;
|
||||
bool up_pressed;
|
||||
bool right_pressed;
|
||||
bool down_pressed;
|
||||
bool ok_pressed;
|
||||
bool connected;
|
||||
} UsbHidMediaModel;
|
||||
|
||||
static void usb_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);
|
||||
} else if(dir == CanvasDirectionTopToBottom) {
|
||||
canvas_draw_dot(canvas, x, y + 1);
|
||||
} else if(dir == CanvasDirectionRightToLeft) {
|
||||
canvas_draw_dot(canvas, x - 1, y);
|
||||
} else if(dir == CanvasDirectionLeftToRight) {
|
||||
canvas_draw_dot(canvas, x + 1, y);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_hid_media_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidMediaModel* model = context;
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Media");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
// Keypad circles
|
||||
canvas_draw_icon(canvas, 76, 8, &I_Circles_47x47);
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 93, 9, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 96, 12, &I_Volup_8x6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 93, 41, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 96, 45, &I_Voldwn_6x6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 77, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_media_draw_arrow(canvas, 82, 31, CanvasDirectionRightToLeft);
|
||||
usb_hid_media_draw_arrow(canvas, 86, 31, CanvasDirectionRightToLeft);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 109, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_hid_media_draw_arrow(canvas, 112, 31, CanvasDirectionLeftToRight);
|
||||
usb_hid_media_draw_arrow(canvas, 116, 31, CanvasDirectionLeftToRight);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_draw_icon(canvas, 93, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
usb_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);
|
||||
|
||||
// Exit
|
||||
canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit");
|
||||
}
|
||||
|
||||
static void usb_hid_media_process_press(UsbHidMedia* usb_hid_media, InputEvent* event) {
|
||||
with_view_model(
|
||||
usb_hid_media->view,
|
||||
UsbHidMediaModel * model,
|
||||
{
|
||||
if(event->key == InputKeyUp) {
|
||||
model->up_pressed = true;
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = true;
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = true;
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_SCAN_PREVIOUS_TRACK);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = true;
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_SCAN_NEXT_TRACK);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = true;
|
||||
furi_hal_hid_consumer_key_press(HID_CONSUMER_PLAY_PAUSE);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static void hid_media_process_release(UsbHidMedia* usb_hid_media, InputEvent* event) {
|
||||
with_view_model(
|
||||
usb_hid_media->view,
|
||||
UsbHidMediaModel * model,
|
||||
{
|
||||
if(event->key == InputKeyUp) {
|
||||
model->up_pressed = false;
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT);
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = false;
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT);
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = false;
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_SCAN_PREVIOUS_TRACK);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = false;
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_SCAN_NEXT_TRACK);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = false;
|
||||
furi_hal_hid_consumer_key_release(HID_CONSUMER_PLAY_PAUSE);
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static bool usb_hid_media_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidMedia* usb_hid_media = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypePress) {
|
||||
usb_hid_media_process_press(usb_hid_media, event);
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
hid_media_process_release(usb_hid_media, event);
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyBack) {
|
||||
furi_hal_hid_kb_release_all();
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
UsbHidMedia* usb_hid_media_alloc() {
|
||||
UsbHidMedia* usb_hid_media = malloc(sizeof(UsbHidMedia));
|
||||
usb_hid_media->view = view_alloc();
|
||||
view_set_context(usb_hid_media->view, usb_hid_media);
|
||||
view_allocate_model(usb_hid_media->view, ViewModelTypeLocking, sizeof(UsbHidMediaModel));
|
||||
view_set_draw_callback(usb_hid_media->view, usb_hid_media_draw_callback);
|
||||
view_set_input_callback(usb_hid_media->view, usb_hid_media_input_callback);
|
||||
|
||||
with_view_model(
|
||||
usb_hid_media->view, UsbHidMediaModel * model, { model->connected = true; }, true);
|
||||
|
||||
return usb_hid_media;
|
||||
}
|
||||
|
||||
void usb_hid_media_free(UsbHidMedia* usb_hid_media) {
|
||||
furi_assert(usb_hid_media);
|
||||
view_free(usb_hid_media->view);
|
||||
free(usb_hid_media);
|
||||
}
|
||||
|
||||
View* usb_hid_media_get_view(UsbHidMedia* usb_hid_media) {
|
||||
furi_assert(usb_hid_media);
|
||||
return usb_hid_media->view;
|
||||
}
|
||||
|
||||
void usb_hid_media_set_connected_status(UsbHidMedia* usb_hid_media, bool connected) {
|
||||
furi_assert(usb_hid_media);
|
||||
with_view_model(
|
||||
usb_hid_media->view, UsbHidMediaModel * model, { model->connected = connected; }, true);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct UsbHidMedia UsbHidMedia;
|
||||
|
||||
UsbHidMedia* usb_hid_media_alloc();
|
||||
|
||||
void usb_hid_media_free(UsbHidMedia* usb_hid_media);
|
||||
|
||||
View* usb_hid_media_get_view(UsbHidMedia* usb_hid_media);
|
||||
|
||||
void usb_hid_media_set_connected_status(UsbHidMedia* usb_hid_media, bool connected);
|
||||
@@ -1,215 +0,0 @@
|
||||
#include "usb_hid_mouse.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <gui/elements.h>
|
||||
#include <USB_Keyboard_icons.h>
|
||||
|
||||
struct UsbHidMouse {
|
||||
View* view;
|
||||
};
|
||||
#define MOUSE_MOVE_SHORT 5
|
||||
#define MOUSE_MOVE_LONG 20
|
||||
|
||||
typedef struct {
|
||||
bool left_pressed;
|
||||
bool up_pressed;
|
||||
bool right_pressed;
|
||||
bool down_pressed;
|
||||
bool left_mouse_pressed;
|
||||
bool left_mouse_held;
|
||||
bool right_mouse_pressed;
|
||||
bool connected;
|
||||
} UsbHidMouseModel;
|
||||
|
||||
static void usb_hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidMouseModel* model = context;
|
||||
|
||||
// Header
|
||||
/*if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}*/
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
if(model->left_mouse_held == true) {
|
||||
elements_multiline_text_aligned(canvas, 0, 62, AlignLeft, AlignBottom, "Selecting...");
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit");
|
||||
}
|
||||
|
||||
// Keypad circles
|
||||
canvas_draw_icon(canvas, 64, 8, &I_Circles_47x47);
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 81, 9, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 81, 41, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 84, 43, &I_Pin_arrow_down_7x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 65, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 67, 28, &I_Pin_arrow_left_9x7);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 97, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 99, 28, &I_Pin_arrow_right_9x7);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Ok
|
||||
if(model->left_mouse_pressed) {
|
||||
canvas_draw_icon(canvas, 81, 25, &I_Ok_btn_pressed_13x13);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 83, 27, &I_Left_mouse_icon_9x9);
|
||||
}
|
||||
|
||||
// Back
|
||||
if(model->right_mouse_pressed) {
|
||||
canvas_draw_icon(canvas, 108, 48, &I_Ok_btn_pressed_13x13);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 110, 50, &I_Right_mouse_icon_9x9);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_hid_mouse_process(UsbHidMouse* usb_hid_mouse, InputEvent* event) {
|
||||
with_view_model(
|
||||
usb_hid_mouse->view,
|
||||
UsbHidMouseModel * model,
|
||||
{
|
||||
if(event->key == InputKeyBack) {
|
||||
if(event->type == InputTypeShort) {
|
||||
furi_hal_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
|
||||
furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
|
||||
} else if(event->type == InputTypePress) {
|
||||
model->right_mouse_pressed = true;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
model->right_mouse_pressed = false;
|
||||
}
|
||||
} else if(event->key == InputKeyOk) {
|
||||
if(event->type == InputTypeShort) {
|
||||
// Just release if it was being held before
|
||||
if(!model->left_mouse_held) furi_hal_hid_mouse_press(HID_MOUSE_BTN_LEFT);
|
||||
furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT);
|
||||
model->left_mouse_held = false;
|
||||
} else if(event->type == InputTypeLong) {
|
||||
furi_hal_hid_mouse_press(HID_MOUSE_BTN_LEFT);
|
||||
model->left_mouse_held = true;
|
||||
model->left_mouse_pressed = true;
|
||||
} else if(event->type == InputTypePress) {
|
||||
model->left_mouse_pressed = true;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
// 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_hid_mouse_move(MOUSE_MOVE_SHORT, 0);
|
||||
} else if(event->type == InputTypeRepeat) {
|
||||
furi_hal_hid_mouse_move(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_hid_mouse_move(-MOUSE_MOVE_SHORT, 0);
|
||||
} else if(event->type == InputTypeRepeat) {
|
||||
furi_hal_hid_mouse_move(-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_hid_mouse_move(0, MOUSE_MOVE_SHORT);
|
||||
} else if(event->type == InputTypeRepeat) {
|
||||
furi_hal_hid_mouse_move(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_hid_mouse_move(0, -MOUSE_MOVE_SHORT);
|
||||
} else if(event->type == InputTypeRepeat) {
|
||||
furi_hal_hid_mouse_move(0, -MOUSE_MOVE_LONG);
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
model->up_pressed = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
static bool usb_hid_mouse_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
UsbHidMouse* usb_hid_mouse = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeLong && event->key == InputKeyBack) {
|
||||
furi_hal_hid_mouse_release(HID_MOUSE_BTN_LEFT);
|
||||
furi_hal_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
|
||||
} else {
|
||||
usb_hid_mouse_process(usb_hid_mouse, event);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
UsbHidMouse* usb_hid_mouse_alloc() {
|
||||
UsbHidMouse* usb_hid_mouse = malloc(sizeof(UsbHidMouse));
|
||||
usb_hid_mouse->view = view_alloc();
|
||||
view_set_context(usb_hid_mouse->view, usb_hid_mouse);
|
||||
view_allocate_model(usb_hid_mouse->view, ViewModelTypeLocking, sizeof(UsbHidMouseModel));
|
||||
view_set_draw_callback(usb_hid_mouse->view, usb_hid_mouse_draw_callback);
|
||||
view_set_input_callback(usb_hid_mouse->view, usb_hid_mouse_input_callback);
|
||||
|
||||
with_view_model(
|
||||
usb_hid_mouse->view, UsbHidMouseModel * model, { model->connected = true; }, true);
|
||||
|
||||
return usb_hid_mouse;
|
||||
}
|
||||
|
||||
void usb_hid_mouse_free(UsbHidMouse* usb_hid_mouse) {
|
||||
furi_assert(usb_hid_mouse);
|
||||
view_free(usb_hid_mouse->view);
|
||||
free(usb_hid_mouse);
|
||||
}
|
||||
|
||||
View* usb_hid_mouse_get_view(UsbHidMouse* usb_hid_mouse) {
|
||||
furi_assert(usb_hid_mouse);
|
||||
return usb_hid_mouse->view;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct UsbHidMouse UsbHidMouse;
|
||||
|
||||
UsbHidMouse* usb_hid_mouse_alloc();
|
||||
|
||||
void usb_hid_mouse_free(UsbHidMouse* usb_hid_mouse);
|
||||
|
||||
View* usb_hid_mouse_get_view(UsbHidMouse* usb_hid_mouse);
|
||||
|
||||
void usb_hid_mouse_set_connected_status(UsbHidMouse* usb_hid_mouse, bool connected);
|
||||
@@ -1,156 +0,0 @@
|
||||
#include "usb_hid_mouse_jiggler.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include <USB_Keyboard_icons.h>
|
||||
|
||||
#define TAG "HidMouseJiggler"
|
||||
|
||||
#define LENGTH(x) (int)(sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
struct HidMouseJiggler {
|
||||
View* view;
|
||||
FuriTimer* timer;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool running;
|
||||
int interval_idx;
|
||||
uint8_t counter;
|
||||
} HidMouseJigglerModel;
|
||||
|
||||
const int intervals[6] = {500, 2000, 5000, 10000, 30000, 60000};
|
||||
|
||||
static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
HidMouseJigglerModel* model = context;
|
||||
|
||||
// Header
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 2, AlignLeft, AlignTop, "Mouse Jiggler");
|
||||
|
||||
// Timeout
|
||||
elements_multiline_text(canvas, AlignLeft, 26, "Interval (ms):");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(model->interval_idx != 0) canvas_draw_icon(canvas, 74, 19, &I_ButtonLeft_4x7);
|
||||
if(model->interval_idx != LENGTH(intervals) - 1)
|
||||
canvas_draw_icon(canvas, 80, 19, &I_ButtonRight_4x7);
|
||||
FuriString* interval_str = furi_string_alloc_printf("%d", intervals[model->interval_idx]);
|
||||
elements_multiline_text(canvas, 91, 26, furi_string_get_cstr(interval_str));
|
||||
furi_string_free(interval_str);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text(canvas, AlignLeft, 40, "Press Start\nto jiggle");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
// Ok
|
||||
canvas_draw_icon(canvas, 63, 30, &I_Space_65x18);
|
||||
if(model->running) {
|
||||
elements_slightly_rounded_box(canvas, 66, 32, 60, 13);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 74, 34, &I_Ok_btn_9x9);
|
||||
if(model->running) {
|
||||
elements_multiline_text_aligned(canvas, 91, 41, AlignLeft, AlignBottom, "Stop");
|
||||
} else {
|
||||
elements_multiline_text_aligned(canvas, 91, 41, AlignLeft, AlignBottom, "Start");
|
||||
}
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Back
|
||||
canvas_draw_icon(canvas, 74, 54, &I_Pin_back_arrow_10x8);
|
||||
elements_multiline_text_aligned(canvas, 91, 62, AlignLeft, AlignBottom, "Quit");
|
||||
}
|
||||
|
||||
static void hid_mouse_jiggler_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
HidMouseJiggler* hid_mouse_jiggler = context;
|
||||
with_view_model(
|
||||
hid_mouse_jiggler->view,
|
||||
HidMouseJigglerModel * model,
|
||||
{
|
||||
if(model->running) {
|
||||
model->counter++;
|
||||
furi_hal_hid_mouse_move(
|
||||
(model->counter % 2 == 0) ? MOUSE_MOVE_SHORT : -MOUSE_MOVE_SHORT, 0);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
static void hid_mouse_jiggler_exit_callback(void* context) {
|
||||
furi_assert(context);
|
||||
HidMouseJiggler* hid_mouse_jiggler = context;
|
||||
furi_timer_stop(hid_mouse_jiggler->timer);
|
||||
}
|
||||
|
||||
static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
HidMouseJiggler* hid_mouse_jiggler = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
with_view_model(
|
||||
hid_mouse_jiggler->view,
|
||||
HidMouseJigglerModel * model,
|
||||
{
|
||||
if(event->type == InputTypePress && event->key == InputKeyOk) {
|
||||
model->running = !model->running;
|
||||
if(model->running) {
|
||||
furi_timer_stop(hid_mouse_jiggler->timer);
|
||||
furi_timer_start(hid_mouse_jiggler->timer, intervals[model->interval_idx]);
|
||||
};
|
||||
consumed = true;
|
||||
}
|
||||
if(event->type == InputTypePress && event->key == InputKeyRight && !model->running &&
|
||||
model->interval_idx < LENGTH(intervals) - 1) {
|
||||
model->interval_idx++;
|
||||
consumed = true;
|
||||
}
|
||||
if(event->type == InputTypePress && event->key == InputKeyLeft && !model->running &&
|
||||
model->interval_idx > 0) {
|
||||
model->interval_idx--;
|
||||
consumed = true;
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
HidMouseJiggler* hid_mouse_jiggler_alloc() {
|
||||
HidMouseJiggler* hid_mouse_jiggler = malloc(sizeof(HidMouseJiggler));
|
||||
|
||||
hid_mouse_jiggler->view = view_alloc();
|
||||
view_set_context(hid_mouse_jiggler->view, hid_mouse_jiggler);
|
||||
view_allocate_model(
|
||||
hid_mouse_jiggler->view, ViewModelTypeLocking, sizeof(HidMouseJigglerModel));
|
||||
view_set_draw_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_draw_callback);
|
||||
view_set_input_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_input_callback);
|
||||
view_set_exit_callback(hid_mouse_jiggler->view, hid_mouse_jiggler_exit_callback);
|
||||
|
||||
hid_mouse_jiggler->timer = furi_timer_alloc(
|
||||
hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler);
|
||||
|
||||
with_view_model(
|
||||
hid_mouse_jiggler->view, HidMouseJigglerModel * model, { model->interval_idx = 2; }, true);
|
||||
|
||||
return hid_mouse_jiggler;
|
||||
}
|
||||
|
||||
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler) {
|
||||
furi_assert(hid_mouse_jiggler);
|
||||
|
||||
furi_timer_stop(hid_mouse_jiggler->timer);
|
||||
furi_timer_free(hid_mouse_jiggler->timer);
|
||||
|
||||
view_free(hid_mouse_jiggler->view);
|
||||
|
||||
free(hid_mouse_jiggler);
|
||||
}
|
||||
|
||||
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler) {
|
||||
furi_assert(hid_mouse_jiggler);
|
||||
return hid_mouse_jiggler->view;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
#define MOUSE_MOVE_SHORT 5
|
||||
#define MOUSE_MOVE_LONG 20
|
||||
|
||||
typedef struct HidMouseJiggler HidMouseJiggler;
|
||||
|
||||
HidMouseJiggler* hid_mouse_jiggler_alloc();
|
||||
|
||||
void hid_mouse_jiggler_free(HidMouseJiggler* hid_mouse_jiggler);
|
||||
|
||||
View* hid_mouse_jiggler_get_view(HidMouseJiggler* hid_mouse_jiggler);
|
||||