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
This commit is contained in:
MX 2023-02-17 04:27:01 +03:00
parent fd46bd1886
commit 5b0f74bffa
No known key found for this signature in database
GPG key ID: 7CCC66B7DBDD1C83
42 changed files with 20 additions and 1519 deletions

View file

@ -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)

View file

@ -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",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 174 B

View file

@ -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},
},
};

View file

@ -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.

View file

@ -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",
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -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;
}

View file

@ -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;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 B

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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);