bt_mouse.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "bt_mouse.h"
  2. #include "../tracking/main_loop.h"
  3. #include <furi.h>
  4. #include <furi_hal_bt.h>
  5. #include <furi_hal_bt_hid.h>
  6. #include <furi_hal_usb_hid.h>
  7. #include <bt/bt_service/bt.h>
  8. #include <gui/elements.h>
  9. #include <notification/notification.h>
  10. #include <notification/notification_messages.h>
  11. struct BtMouse {
  12. View* view;
  13. ViewDispatcher* view_dispatcher;
  14. Bt* bt;
  15. NotificationApp* notifications;
  16. };
  17. #define MOUSE_MOVE_SHORT 5
  18. #define MOUSE_MOVE_LONG 20
  19. static void bt_mouse_draw_callback(Canvas* canvas, void* context) {
  20. UNUSED(context);
  21. canvas_clear(canvas);
  22. canvas_set_font(canvas, FontPrimary);
  23. canvas_draw_str(canvas, 0, 10, "Bluetooth Mouse mode");
  24. canvas_set_font(canvas, FontSecondary);
  25. canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
  26. }
  27. static void bt_mouse_process(BtMouse* bt_mouse, InputEvent* event) {
  28. with_view_model(
  29. bt_mouse->view,
  30. void * model,
  31. {
  32. UNUSED(model);
  33. if (event->key == InputKeyUp) {
  34. if (event->type == InputTypePress) {
  35. furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_LEFT);
  36. } else if (event->type == InputTypeRelease) {
  37. furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_LEFT);
  38. }
  39. } else if (event->key == InputKeyDown) {
  40. if (event->type == InputTypePress) {
  41. furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_RIGHT);
  42. } else if (event->type == InputTypeRelease) {
  43. furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_RIGHT);
  44. }
  45. } else if (event->key == InputKeyOk) {
  46. if (event->type == InputTypePress) {
  47. furi_hal_bt_hid_mouse_press(HID_MOUSE_BTN_WHEEL);
  48. } else if (event->type == InputTypeRelease) {
  49. furi_hal_bt_hid_mouse_release(HID_MOUSE_BTN_WHEEL);
  50. }
  51. }
  52. },
  53. true);
  54. }
  55. static bool bt_mouse_input_callback(InputEvent* event, void* context) {
  56. furi_assert(context);
  57. BtMouse* bt_mouse = context;
  58. bool consumed = false;
  59. if (event->type == InputTypeLong && event->key == InputKeyBack) {
  60. furi_hal_bt_hid_mouse_release_all();
  61. } else {
  62. bt_mouse_process(bt_mouse, event);
  63. consumed = true;
  64. }
  65. return consumed;
  66. }
  67. void bt_mouse_connection_status_changed_callback(BtStatus status, void* context) {
  68. furi_assert(context);
  69. BtMouse* bt_mouse = context;
  70. bool connected = (status == BtStatusConnected);
  71. if (connected) {
  72. notification_internal_message(bt_mouse->notifications, &sequence_set_blue_255);
  73. } else {
  74. notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
  75. }
  76. //with_view_model(
  77. // bt_mouse->view, void * model, { model->connected = connected; }, true);
  78. }
  79. void bt_mouse_enter_callback(void *context) {
  80. furi_assert(context);
  81. BtMouse* bt_mouse = context;
  82. bt_mouse->bt = furi_record_open(RECORD_BT);
  83. bt_mouse->notifications = furi_record_open(RECORD_NOTIFICATION);
  84. bt_set_status_changed_callback(bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse);
  85. furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard));
  86. furi_hal_bt_start_advertising();
  87. tracking_begin();
  88. view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
  89. }
  90. bool bt_mouse_custom_callback(uint32_t event, void* context) {
  91. UNUSED(event);
  92. furi_assert(context);
  93. BtMouse* bt_mouse = context;
  94. tracking_step(furi_hal_bt_hid_mouse_move);
  95. view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
  96. return true;
  97. }
  98. void bt_mouse_exit_callback(void *context) {
  99. furi_assert(context);
  100. BtMouse* bt_mouse = context;
  101. tracking_end();
  102. notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
  103. furi_hal_bt_stop_advertising();
  104. bt_set_profile(bt_mouse->bt, BtProfileSerial);
  105. furi_record_close(RECORD_NOTIFICATION);
  106. bt_mouse->notifications = NULL;
  107. furi_record_close(RECORD_BT);
  108. bt_mouse->bt = NULL;
  109. }
  110. BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) {
  111. BtMouse* bt_mouse = malloc(sizeof(BtMouse));
  112. bt_mouse->view = view_alloc();
  113. bt_mouse->view_dispatcher = view_dispatcher;
  114. view_set_context(bt_mouse->view, bt_mouse);
  115. view_set_draw_callback(bt_mouse->view, bt_mouse_draw_callback);
  116. view_set_input_callback(bt_mouse->view, bt_mouse_input_callback);
  117. view_set_enter_callback(bt_mouse->view, bt_mouse_enter_callback);
  118. view_set_custom_callback(bt_mouse->view, bt_mouse_custom_callback);
  119. view_set_exit_callback(bt_mouse->view, bt_mouse_exit_callback);
  120. return bt_mouse;
  121. }
  122. void bt_mouse_free(BtMouse* bt_mouse) {
  123. furi_assert(bt_mouse);
  124. view_free(bt_mouse->view);
  125. free(bt_mouse);
  126. }
  127. View* bt_mouse_get_view(BtMouse* bt_mouse) {
  128. furi_assert(bt_mouse);
  129. return bt_mouse->view;
  130. }