bt_hid_tiktok.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "bt_hid_tiktok.h"
  2. #include <furi.h>
  3. #include <furi_hal_bt_hid.h>
  4. #include <furi_hal_usb_hid.h>
  5. #include <gui/elements.h>
  6. #include "bt_hid_icons.h"
  7. struct BtHidTikTok {
  8. View* view;
  9. };
  10. typedef struct {
  11. bool left_pressed;
  12. bool up_pressed;
  13. bool right_pressed;
  14. bool down_pressed;
  15. bool ok_pressed;
  16. bool connected;
  17. } BtHidTikTokModel;
  18. static void bt_hid_tiktok_draw_callback(Canvas* canvas, void* context) {
  19. furi_assert(context);
  20. BtHidTikTokModel* model = context;
  21. // Header
  22. if(model->connected) {
  23. canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
  24. } else {
  25. canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
  26. }
  27. canvas_set_font(canvas, FontPrimary);
  28. elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "TikTok");
  29. canvas_set_font(canvas, FontSecondary);
  30. // Keypad circles
  31. canvas_draw_icon(canvas, 76, 8, &I_Circles_47x47);
  32. // Up
  33. if(model->up_pressed) {
  34. canvas_set_bitmap_mode(canvas, 1);
  35. canvas_draw_icon(canvas, 93, 9, &I_Pressed_Button_13x13);
  36. canvas_set_bitmap_mode(canvas, 0);
  37. canvas_set_color(canvas, ColorWhite);
  38. }
  39. canvas_draw_icon(canvas, 96, 11, &I_Arr_up_7x9);
  40. canvas_set_color(canvas, ColorBlack);
  41. // Down
  42. if(model->down_pressed) {
  43. canvas_set_bitmap_mode(canvas, 1);
  44. canvas_draw_icon(canvas, 93, 41, &I_Pressed_Button_13x13);
  45. canvas_set_bitmap_mode(canvas, 0);
  46. canvas_set_color(canvas, ColorWhite);
  47. }
  48. canvas_draw_icon(canvas, 96, 44, &I_Arr_dwn_7x9);
  49. canvas_set_color(canvas, ColorBlack);
  50. // Left
  51. if(model->left_pressed) {
  52. canvas_set_bitmap_mode(canvas, 1);
  53. canvas_draw_icon(canvas, 77, 25, &I_Pressed_Button_13x13);
  54. canvas_set_bitmap_mode(canvas, 0);
  55. canvas_set_color(canvas, ColorWhite);
  56. }
  57. canvas_draw_icon(canvas, 81, 29, &I_Voldwn_6x6);
  58. canvas_set_color(canvas, ColorBlack);
  59. // Right
  60. if(model->right_pressed) {
  61. canvas_set_bitmap_mode(canvas, 1);
  62. canvas_draw_icon(canvas, 109, 25, &I_Pressed_Button_13x13);
  63. canvas_set_bitmap_mode(canvas, 0);
  64. canvas_set_color(canvas, ColorWhite);
  65. }
  66. canvas_draw_icon(canvas, 111, 29, &I_Volup_8x6);
  67. canvas_set_color(canvas, ColorBlack);
  68. // Ok
  69. if(model->ok_pressed) {
  70. canvas_draw_icon(canvas, 91, 23, &I_Like_pressed_17x17);
  71. } else {
  72. canvas_draw_icon(canvas, 94, 27, &I_Like_def_11x9);
  73. }
  74. // Exit
  75. canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8);
  76. canvas_set_font(canvas, FontSecondary);
  77. elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit");
  78. }
  79. static void bt_hid_tiktok_process_press(BtHidTikTok* bt_hid_tiktok, InputEvent* event) {
  80. with_view_model(
  81. bt_hid_tiktok->view,
  82. BtHidTikTokModel * model,
  83. {
  84. if(event->key == InputKeyUp) {
  85. model->up_pressed = true;
  86. } else if(event->key == InputKeyDown) {
  87. model->down_pressed = true;
  88. } else if(event->key == InputKeyLeft) {
  89. model->left_pressed = true;
  90. furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_DECREMENT);
  91. } else if(event->key == InputKeyRight) {
  92. model->right_pressed = true;
  93. furi_hal_bt_hid_consumer_key_press(HID_CONSUMER_VOLUME_INCREMENT);
  94. } else if(event->key == InputKeyOk) {
  95. model->ok_pressed = true;
  96. }
  97. },
  98. true);
  99. }
  100. static void bt_hid_tiktok_process_release(BtHidTikTok* bt_hid_tiktok, InputEvent* event) {
  101. with_view_model(
  102. bt_hid_tiktok->view,
  103. BtHidTikTokModel * model,
  104. {
  105. if(event->key == InputKeyUp) {
  106. model->up_pressed = false;
  107. } else if(event->key == InputKeyDown) {
  108. model->down_pressed = false;
  109. } else if(event->key == InputKeyLeft) {
  110. model->left_pressed = false;
  111. furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_DECREMENT);
  112. } else if(event->key == InputKeyRight) {
  113. model->right_pressed = false;
  114. furi_hal_bt_hid_consumer_key_release(HID_CONSUMER_VOLUME_INCREMENT);
  115. } else if(event->key == InputKeyOk) {
  116. model->ok_pressed = false;
  117. }
  118. },
  119. true);
  120. }
  121. static bool bt_hid_tiktok_input_callback(InputEvent* event, void* context) {
  122. furi_assert(context);
  123. BtHidTikTok* bt_hid_tiktok = context;
  124. bool consumed = false;
  125. if(event->type == InputTypePress) {
  126. bt_hid_tiktok_process_press(bt_hid_tiktok, event);
  127. consumed = true;
  128. } else if(event->type == InputTypeRelease) {
  129. bt_hid_tiktok_process_release(bt_hid_tiktok, event);
  130. consumed = true;
  131. } else if(event->type == InputTypeShort) {
  132. if(event->key == InputKeyOk) {
  133. furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
  134. furi_delay_ms(50);
  135. furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
  136. furi_delay_ms(50);
  137. furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
  138. furi_delay_ms(50);
  139. furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
  140. consumed = true;
  141. } else if(event->key == InputKeyUp) {
  142. // Emulate up swipe
  143. furi_hal_bt_hid_mouse_scroll(-6);
  144. furi_hal_bt_hid_mouse_scroll(-12);
  145. furi_hal_bt_hid_mouse_scroll(-19);
  146. furi_hal_bt_hid_mouse_scroll(-12);
  147. furi_hal_bt_hid_mouse_scroll(-6);
  148. consumed = true;
  149. } else if(event->key == InputKeyDown) {
  150. // Emulate down swipe
  151. furi_hal_bt_hid_mouse_scroll(6);
  152. furi_hal_bt_hid_mouse_scroll(12);
  153. furi_hal_bt_hid_mouse_scroll(19);
  154. furi_hal_bt_hid_mouse_scroll(12);
  155. furi_hal_bt_hid_mouse_scroll(6);
  156. consumed = true;
  157. } else if(event->key == InputKeyBack) {
  158. furi_hal_bt_hid_consumer_key_release_all();
  159. consumed = true;
  160. }
  161. }
  162. return consumed;
  163. }
  164. BtHidTikTok* bt_hid_tiktok_alloc() {
  165. BtHidTikTok* bt_hid_tiktok = malloc(sizeof(BtHidTikTok));
  166. bt_hid_tiktok->view = view_alloc();
  167. view_set_context(bt_hid_tiktok->view, bt_hid_tiktok);
  168. view_allocate_model(bt_hid_tiktok->view, ViewModelTypeLocking, sizeof(BtHidTikTokModel));
  169. view_set_draw_callback(bt_hid_tiktok->view, bt_hid_tiktok_draw_callback);
  170. view_set_input_callback(bt_hid_tiktok->view, bt_hid_tiktok_input_callback);
  171. return bt_hid_tiktok;
  172. }
  173. void bt_hid_tiktok_free(BtHidTikTok* bt_hid_tiktok) {
  174. furi_assert(bt_hid_tiktok);
  175. view_free(bt_hid_tiktok->view);
  176. free(bt_hid_tiktok);
  177. }
  178. View* bt_hid_tiktok_get_view(BtHidTikTok* bt_hid_tiktok) {
  179. furi_assert(bt_hid_tiktok);
  180. return bt_hid_tiktok->view;
  181. }
  182. void bt_hid_tiktok_set_connected_status(BtHidTikTok* bt_hid_tiktok, bool connected) {
  183. furi_assert(bt_hid_tiktok);
  184. with_view_model(
  185. bt_hid_tiktok->view, BtHidTikTokModel * model, { model->connected = connected; }, true);
  186. }