bt_mouse.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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(
  85. bt_mouse->bt, bt_mouse_connection_status_changed_callback, bt_mouse);
  86. furi_assert(bt_set_profile(bt_mouse->bt, BtProfileHidKeyboard));
  87. furi_hal_bt_start_advertising();
  88. tracking_begin();
  89. view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
  90. }
  91. bool bt_mouse_custom_callback(uint32_t event, void* context) {
  92. UNUSED(event);
  93. furi_assert(context);
  94. BtMouse* bt_mouse = context;
  95. tracking_step(furi_hal_bt_hid_mouse_move);
  96. view_dispatcher_send_custom_event(bt_mouse->view_dispatcher, 0);
  97. return true;
  98. }
  99. void bt_mouse_exit_callback(void* context) {
  100. furi_assert(context);
  101. BtMouse* bt_mouse = context;
  102. tracking_end();
  103. notification_internal_message(bt_mouse->notifications, &sequence_reset_blue);
  104. furi_hal_bt_stop_advertising();
  105. bt_set_profile(bt_mouse->bt, BtProfileSerial);
  106. furi_record_close(RECORD_NOTIFICATION);
  107. bt_mouse->notifications = NULL;
  108. furi_record_close(RECORD_BT);
  109. bt_mouse->bt = NULL;
  110. }
  111. BtMouse* bt_mouse_alloc(ViewDispatcher* view_dispatcher) {
  112. BtMouse* bt_mouse = malloc(sizeof(BtMouse));
  113. bt_mouse->view = view_alloc();
  114. bt_mouse->view_dispatcher = view_dispatcher;
  115. view_set_context(bt_mouse->view, bt_mouse);
  116. view_set_draw_callback(bt_mouse->view, bt_mouse_draw_callback);
  117. view_set_input_callback(bt_mouse->view, bt_mouse_input_callback);
  118. view_set_enter_callback(bt_mouse->view, bt_mouse_enter_callback);
  119. view_set_custom_callback(bt_mouse->view, bt_mouse_custom_callback);
  120. view_set_exit_callback(bt_mouse->view, bt_mouse_exit_callback);
  121. return bt_mouse;
  122. }
  123. void bt_mouse_free(BtMouse* bt_mouse) {
  124. furi_assert(bt_mouse);
  125. view_free(bt_mouse->view);
  126. free(bt_mouse);
  127. }
  128. View* bt_mouse_get_view(BtMouse* bt_mouse) {
  129. furi_assert(bt_mouse);
  130. return bt_mouse->view;
  131. }