[FL-2882] BLE tiktok controller (#1859)
* 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: あく <alleteam@gmail.com>
| @ -5,6 +5,5 @@ App( | |||||||
|     provides=[ |     provides=[ | ||||||
|         "music_player", |         "music_player", | ||||||
|         "snake_game", |         "snake_game", | ||||||
|         "bt_hid", |  | ||||||
|     ], |     ], | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -1,15 +1,10 @@ | |||||||
| App( | App( | ||||||
|     appid="bt_hid", |     appid="bt_hid", | ||||||
|     name="Bluetooth Remote", |     name="Bluetooth Remote", | ||||||
|     apptype=FlipperAppType.PLUGIN, |     apptype=FlipperAppType.EXTERNAL, | ||||||
|     entry_point="bt_hid_app", |     entry_point="bt_hid_app", | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     cdefines=["APP_BLE_HID"], |  | ||||||
|     requires=[ |  | ||||||
|         "bt", |  | ||||||
|         "gui", |  | ||||||
|     ], |  | ||||||
|     order=10, |  | ||||||
|     fap_icon="bt_remote_10px.png", |  | ||||||
|     fap_category="Tools", |     fap_category="Tools", | ||||||
|  |     fap_icon="bt_remote_10px.png", | ||||||
|  |     fap_icon_assets="assets", | ||||||
| ) | ) | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Arr_dwn_7x9.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Arr_up_7x9.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Ble_connected_15x15.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Button_18x18.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Circles_47x47.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Left_mouse_icon_9x9.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Like_def_11x9.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Like_pressed_17x17.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Ok_btn_pressed_13x13.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Pressed_Button_13x13.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Right_mouse_icon_9x9.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Space_65x18.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Voldwn_6x6.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								applications/plugins/bt_hid_app/assets/Volup_8x6.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.5 KiB | 
| @ -9,6 +9,7 @@ enum BtDebugSubmenuIndex { | |||||||
|     BtHidSubmenuIndexKeynote, |     BtHidSubmenuIndexKeynote, | ||||||
|     BtHidSubmenuIndexKeyboard, |     BtHidSubmenuIndexKeyboard, | ||||||
|     BtHidSubmenuIndexMedia, |     BtHidSubmenuIndexMedia, | ||||||
|  |     BtHidSubmenuIndexTikTok, | ||||||
|     BtHidSubmenuIndexMouse, |     BtHidSubmenuIndexMouse, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -27,6 +28,9 @@ void bt_hid_submenu_callback(void* context, uint32_t index) { | |||||||
|     } else if(index == BtHidSubmenuIndexMouse) { |     } else if(index == BtHidSubmenuIndexMouse) { | ||||||
|         app->view_id = BtHidViewMouse; |         app->view_id = BtHidViewMouse; | ||||||
|         view_dispatcher_switch_to_view(app->view_dispatcher, 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); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -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_keyboard_set_connected_status(bt_hid->bt_hid_keyboard, connected); | ||||||
|     bt_hid_media_set_connected_status(bt_hid->bt_hid_media, 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_mouse_set_connected_status(bt_hid->bt_hid_mouse, connected); | ||||||
|  |     bt_hid_tiktok_set_connected_status(bt_hid->bt_hid_tiktok, connected); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BtHid* bt_hid_app_alloc() { | BtHid* bt_hid_app_alloc() { | ||||||
| @ -91,6 +96,8 @@ BtHid* bt_hid_app_alloc() { | |||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         app->submenu, "Keyboard", BtHidSubmenuIndexKeyboard, bt_hid_submenu_callback, app); |         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, "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); |     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_set_previous_callback(submenu_get_view(app->submenu), bt_hid_exit); | ||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
| @ -127,6 +134,13 @@ BtHid* bt_hid_app_alloc() { | |||||||
|     view_dispatcher_add_view( |     view_dispatcher_add_view( | ||||||
|         app->view_dispatcher, BtHidViewMedia, bt_hid_media_get_view(app->bt_hid_media)); |         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
 |     // Mouse view
 | ||||||
|     app->bt_hid_mouse = bt_hid_mouse_alloc(); |     app->bt_hid_mouse = bt_hid_mouse_alloc(); | ||||||
|     view_set_previous_callback(bt_hid_mouse_get_view(app->bt_hid_mouse), bt_hid_exit_confirm_view); |     view_set_previous_callback(bt_hid_mouse_get_view(app->bt_hid_mouse), bt_hid_exit_confirm_view); | ||||||
| @ -159,6 +173,8 @@ void bt_hid_app_free(BtHid* app) { | |||||||
|     bt_hid_media_free(app->bt_hid_media); |     bt_hid_media_free(app->bt_hid_media); | ||||||
|     view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMouse); |     view_dispatcher_remove_view(app->view_dispatcher, BtHidViewMouse); | ||||||
|     bt_hid_mouse_free(app->bt_hid_mouse); |     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); |     view_dispatcher_free(app->view_dispatcher); | ||||||
| 
 | 
 | ||||||
|     // Close records
 |     // Close records
 | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ | |||||||
| #include "views/bt_hid_keyboard.h" | #include "views/bt_hid_keyboard.h" | ||||||
| #include "views/bt_hid_media.h" | #include "views/bt_hid_media.h" | ||||||
| #include "views/bt_hid_mouse.h" | #include "views/bt_hid_mouse.h" | ||||||
|  | #include "views/bt_hid_tiktok.h" | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     Bt* bt; |     Bt* bt; | ||||||
| @ -25,6 +26,7 @@ typedef struct { | |||||||
|     BtHidKeyboard* bt_hid_keyboard; |     BtHidKeyboard* bt_hid_keyboard; | ||||||
|     BtHidMedia* bt_hid_media; |     BtHidMedia* bt_hid_media; | ||||||
|     BtHidMouse* bt_hid_mouse; |     BtHidMouse* bt_hid_mouse; | ||||||
|  |     BtHidTikTok* bt_hid_tiktok; | ||||||
|     uint32_t view_id; |     uint32_t view_id; | ||||||
| } BtHid; | } BtHid; | ||||||
| 
 | 
 | ||||||
| @ -34,5 +36,6 @@ typedef enum { | |||||||
|     BtHidViewKeyboard, |     BtHidViewKeyboard, | ||||||
|     BtHidViewMedia, |     BtHidViewMedia, | ||||||
|     BtHidViewMouse, |     BtHidViewMouse, | ||||||
|  |     BtHidViewTikTok, | ||||||
|     BtHidViewExitConfirm, |     BtHidViewExitConfirm, | ||||||
| } BtHidView; | } BtHidView; | ||||||
|  | |||||||
| @ -5,6 +5,8 @@ | |||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| #include <gui/icon_i.h> | #include <gui/icon_i.h> | ||||||
| 
 | 
 | ||||||
|  | #include "bt_hid_icons.h" | ||||||
|  | 
 | ||||||
| struct BtHidKeyboard { | struct BtHidKeyboard { | ||||||
|     View* view; |     View* view; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ | |||||||
| #include <furi_hal_usb_hid.h> | #include <furi_hal_usb_hid.h> | ||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| 
 | 
 | ||||||
|  | #include "bt_hid_icons.h" | ||||||
|  | 
 | ||||||
| struct BtHidKeynote { | struct BtHidKeynote { | ||||||
|     View* view; |     View* view; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ | |||||||
| #include <furi_hal_usb_hid.h> | #include <furi_hal_usb_hid.h> | ||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| 
 | 
 | ||||||
|  | #include "bt_hid_icons.h" | ||||||
|  | 
 | ||||||
| struct BtHidMedia { | struct BtHidMedia { | ||||||
|     View* view; |     View* view; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ | |||||||
| #include <furi_hal_usb_hid.h> | #include <furi_hal_usb_hid.h> | ||||||
| #include <gui/elements.h> | #include <gui/elements.h> | ||||||
| 
 | 
 | ||||||
|  | #include "bt_hid_icons.h" | ||||||
|  | 
 | ||||||
| struct BtHidMouse { | struct BtHidMouse { | ||||||
|     View* view; |     View* view; | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										207
									
								
								applications/plugins/bt_hid_app/views/bt_hid_tiktok.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -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
									
								
								applications/plugins/bt_hid_app/views/bt_hid_tiktok.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -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); | ||||||
 gornekich
						gornekich