Skip to content

Commit

Permalink
[FL-2882] BLE tiktok controller (flipperdevices#1859)
Browse files Browse the repository at this point in the history
* bt hid: introduce tiktok controller
* assets: add bt tiktok assets
* bt hid: finish tiktok draw
* bt hid: add input process to tiktok view
* bt hid: add tiktok swipe emulation
* bt hid: fix exit from tiktok controller
* ble hid: add delay to emulate double tap
* ble hid: change options order
* bt hid: build as external application
* ble hid: fix naming

Co-authored-by: あく <[email protected]>
  • Loading branch information
gornekich and skotopes authored Oct 12, 2022
1 parent 92a738b commit afff1ad
Show file tree
Hide file tree
Showing 25 changed files with 250 additions and 9 deletions.
1 change: 0 additions & 1 deletion applications/plugins/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ App(
provides=[
"music_player",
"snake_game",
"bt_hid",
],
)
11 changes: 3 additions & 8 deletions applications/plugins/bt_hid_app/application.fam
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
App(
appid="bt_hid",
name="Bluetooth Remote",
apptype=FlipperAppType.PLUGIN,
apptype=FlipperAppType.EXTERNAL,
entry_point="bt_hid_app",
stack_size=1 * 1024,
cdefines=["APP_BLE_HID"],
requires=[
"bt",
"gui",
],
order=10,
fap_icon="bt_remote_10px.png",
fap_category="Tools",
fap_icon="bt_remote_10px.png",
fap_icon_assets="assets",
)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions applications/plugins/bt_hid_app/bt_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum BtDebugSubmenuIndex {
BtHidSubmenuIndexKeynote,
BtHidSubmenuIndexKeyboard,
BtHidSubmenuIndexMedia,
BtHidSubmenuIndexTikTok,
BtHidSubmenuIndexMouse,
};

Expand All @@ -27,6 +28,9 @@ void bt_hid_submenu_callback(void* context, uint32_t index) {
} else if(index == BtHidSubmenuIndexMouse) {
app->view_id = BtHidViewMouse;
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewMouse);
} else if(index == BtHidSubmenuIndexTikTok) {
app->view_id = BtHidViewTikTok;
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
}
}

Expand Down Expand Up @@ -65,6 +69,7 @@ void bt_hid_connection_status_changed_callback(BtStatus status, void* context) {
bt_hid_keyboard_set_connected_status(bt_hid->bt_hid_keyboard, connected);
bt_hid_media_set_connected_status(bt_hid->bt_hid_media, connected);
bt_hid_mouse_set_connected_status(bt_hid->bt_hid_mouse, connected);
bt_hid_tiktok_set_connected_status(bt_hid->bt_hid_tiktok, connected);
}

BtHid* bt_hid_app_alloc() {
Expand All @@ -91,6 +96,8 @@ BtHid* bt_hid_app_alloc() {
submenu_add_item(
app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app);
submenu_add_item(app->submenu, "Media", BtHidSubmenuIndexMedia, bt_hid_submenu_callback, app);
submenu_add_item(
app->submenu, "TikTok Controller", BtHidSubmenuIndexTikTok, bt_hid_submenu_callback, app);
submenu_add_item(app->submenu, "Mouse", BtHidSubmenuIndexMouse, bt_hid_submenu_callback, app);
view_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit);
view_dispatcher_add_view(
Expand Down Expand Up @@ -127,6 +134,13 @@ BtHid* bt_hid_app_alloc() {
view_dispatcher_add_view(
app->view_dispatcher, BtHidViewMedia, bt_hid_media_get_view(app->bt_hid_media));

// TikTok view
app->bt_hid_tiktok = bt_hid_tiktok_alloc();
view_set_previous_callback(
bt_hid_tiktok_get_view(app->bt_hid_tiktok), bt_hid_exit_confirm_view);
view_dispatcher_add_view(
app->view_dispatcher, BtHidViewTikTok, bt_hid_tiktok_get_view(app->bt_hid_tiktok));

// Mouse view
app->bt_hid_mouse = bt_hid_mouse_alloc();
view_set_previous_callback(bt_hid_mouse_get_view(app->bt_hid_mouse), bt_hid_exit_confirm_view);
Expand Down Expand Up @@ -159,6 +173,8 @@ void bt_hid_app_free(BtHid* app) {
bt_hid_media_free(app->bt_hid_media);
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMouse);
bt_hid_mouse_free(app->bt_hid_mouse);
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
bt_hid_tiktok_free(app->bt_hid_tiktok);
view_dispatcher_free(app->view_dispatcher);

// Close records
Expand Down
3 changes: 3 additions & 0 deletions applications/plugins/bt_hid_app/bt_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "views/bt_hid_keyboard.h"
#include "views/bt_hid_media.h"
#include "views/bt_hid_mouse.h"
#include "views/bt_hid_tiktok.h"

typedef struct {
Bt* bt;
Expand All @@ -25,6 +26,7 @@ typedef struct {
BtHidKeyboard* bt_hid_keyboard;
BtHidMedia* bt_hid_media;
BtHidMouse* bt_hid_mouse;
BtHidTikTok* bt_hid_tiktok;
uint32_t view_id;
} BtHid;

Expand All @@ -34,5 +36,6 @@ typedef enum {
BtHidViewKeyboard,
BtHidViewMedia,
BtHidViewMouse,
BtHidViewTikTok,
BtHidViewExitConfirm,
} BtHidView;
2 changes: 2 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <gui/elements.h>
#include <gui/icon_i.h>

#include "bt_hid_icons.h"

struct BtHidKeyboard {
View* view;
};
Expand Down
2 changes: 2 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_keynote.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <furi_hal_usb_hid.h>
#include <gui/elements.h>

#include "bt_hid_icons.h"

struct BtHidKeynote {
View* view;
};
Expand Down
2 changes: 2 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_media.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <furi_hal_usb_hid.h>
#include <gui/elements.h>

#include "bt_hid_icons.h"

struct BtHidMedia {
View* view;
};
Expand Down
2 changes: 2 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <furi_hal_usb_hid.h>
#include <gui/elements.h>

#include "bt_hid_icons.h"

struct BtHidMouse {
View* view;
};
Expand Down
207 changes: 207 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_tiktok.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
#include "bt_hid_tiktok.h"
#include <furi.h>
#include <furi_hal_bt_hid.h>
#include <furi_hal_usb_hid.h>
#include <gui/elements.h>

#include "bt_hid_icons.h"

struct BtHidTikTok {
View* view;
};

typedef struct {
bool left_pressed;
bool up_pressed;
bool right_pressed;
bool down_pressed;
bool ok_pressed;
bool connected;
} BtHidTikTokModel;

static void bt_hid_tiktok_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
BtHidTikTokModel* 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, "TikTok");
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, 11, &I_Arr_up_7x9);
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, 44, &I_Arr_dwn_7x9);
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);
}
canvas_draw_icon(canvas, 81, 29, &I_Voldwn_6x6);
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);
}
canvas_draw_icon(canvas, 111, 29, &I_Volup_8x6);
canvas_set_color(canvas, ColorBlack);

// Ok
if(model->ok_pressed) {
canvas_draw_icon(canvas, 91, 23, &I_Like_pressed_17x17);
} else {
canvas_draw_icon(canvas, 94, 27, &I_Like_def_11x9);
}
// 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 bt_hid_tiktok_process_press(BtHidTikTok* bt_hid_tiktok, InputEvent* event) {
with_view_model(
bt_hid_tiktok->view,
BtHidTikTokModel * model,
{
if(event->key == InputKeyUp) {
model->up_pressed = true;
} else if(event->key == InputKeyDown) {
model->down_pressed = true;
} else if(event->key == InputKeyLeft) {
model->left_pressed = true;
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT);
} else if(event->key == InputKeyRight) {
model->right_pressed = true;
furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT);
} else if(event->key == InputKeyOk) {
model->ok_pressed = true;
}
},
true);
}

static void bt_hid_tiktok_process_release(BtHidTikTok* bt_hid_tiktok, InputEvent* event) {
with_view_model(
bt_hid_tiktok->view,
BtHidTikTokModel * model,
{
if(event->key == InputKeyUp) {
model->up_pressed = false;
} else if(event->key == InputKeyDown) {
model->down_pressed = false;
} else if(event->key == InputKeyLeft) {
model->left_pressed = false;
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT);
} else if(event->key == InputKeyRight) {
model->right_pressed = false;
furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT);
} else if(event->key == InputKeyOk) {
model->ok_pressed = false;
}
},
true);
}

static bool bt_hid_tiktok_input_callback(InputEvent* event, void* context) {
furi_assert(context);
BtHidTikTok* bt_hid_tiktok = context;
bool consumed = false;

if(event->type == InputTypePress) {
bt_hid_tiktok_process_press(bt_hid_tiktok, event);
consumed = true;
} else if(event->type == InputTypeRelease) {
bt_hid_tiktok_process_release(bt_hid_tiktok, event);
consumed = true;
} else if(event->type == InputTypeShort) {
if(event->key == InputKeyOk) {
furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
furi_delay_ms(50);
furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
consumed = true;
} else if(event->key == InputKeyUp) {
// Emulate up swipe
furi_hal_bt_hid_mouse_scroll(-6);
furi_hal_bt_hid_mouse_scroll(-12);
furi_hal_bt_hid_mouse_scroll(-19);
furi_hal_bt_hid_mouse_scroll(-12);
furi_hal_bt_hid_mouse_scroll(-6);
consumed = true;
} else if(event->key == InputKeyDown) {
// Emulate down swipe
furi_hal_bt_hid_mouse_scroll(6);
furi_hal_bt_hid_mouse_scroll(12);
furi_hal_bt_hid_mouse_scroll(19);
furi_hal_bt_hid_mouse_scroll(12);
furi_hal_bt_hid_mouse_scroll(6);
consumed = true;
} else if(event->key == InputKeyBack) {
furi_hal_bt_hid_consumer_key_release_all();
consumed = true;
}
}

return consumed;
}

BtHidTikTok* bt_hid_tiktok_alloc() {
BtHidTikTok* bt_hid_tiktok = malloc(sizeof(BtHidTikTok));
bt_hid_tiktok->view = view_alloc();
view_set_context(bt_hid_tiktok->view, bt_hid_tiktok);
view_allocate_model(bt_hid_tiktok->view, ViewModelTypeLocking, sizeof(BtHidTikTokModel));
view_set_draw_callback(bt_hid_tiktok->view, bt_hid_tiktok_draw_callback);
view_set_input_callback(bt_hid_tiktok->view, bt_hid_tiktok_input_callback);

return bt_hid_tiktok;
}

void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok) {
furi_assert(bt_hid_tiktok);
view_free(bt_hid_tiktok->view);
free(bt_hid_tiktok);
}

View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok) {
furi_assert(bt_hid_tiktok);
return bt_hid_tiktok->view;
}

void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected) {
furi_assert(bt_hid_tiktok);
with_view_model(
bt_hid_tiktok->view, BtHidTikTokModel * model, { model->connected = connected; }, true);
}
13 changes: 13 additions & 0 deletions applications/plugins/bt_hid_app/views/bt_hid_tiktok.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <gui/view.h>

typedef struct BtHidTikTok BtHidTikTok;

BtHidTikTok* bt_hid_tiktok_alloc();

void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok);

View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok);

void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected);

0 comments on commit afff1ad

Please sign in to comment.