ble_keyboard.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include <furi.h>
  2. #include <gui/gui.h>
  3. #include <input/input.h>
  4. #include <bt/bt_service/bt.h>
  5. #include <furi-hal-bt.h>
  6. #include <furi-hal-bt-hid.h>
  7. #include <furi-hal-usb-hid.h>
  8. #define TAG "BleKeyboardApp"
  9. typedef enum {
  10. EventTypeInput,
  11. } EventType;
  12. typedef struct {
  13. union {
  14. InputEvent input;
  15. };
  16. EventType type;
  17. } BleKeyboardEvent;
  18. static void ble_keyboard_render_callback(Canvas* canvas, void* ctx) {
  19. canvas_clear(canvas);
  20. canvas_set_font(canvas, FontPrimary);
  21. canvas_draw_str(canvas, 0, 10, "BLE keypad demo");
  22. canvas_set_font(canvas, FontSecondary);
  23. canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
  24. }
  25. static void ble_keyboard_input_callback(InputEvent* input_event, void* ctx) {
  26. osMessageQueueId_t event_queue = ctx;
  27. BleKeyboardEvent event;
  28. event.type = EventTypeInput;
  29. event.input = *input_event;
  30. osMessageQueuePut(event_queue, &event, 0, osWaitForever);
  31. }
  32. int32_t ble_keyboard_app(void* p) {
  33. Bt* bt = furi_record_open("bt");
  34. if(!bt_set_profile(bt, BtProfileHidKeyboard)) {
  35. FURI_LOG_E(TAG, "Failed to switch profile");
  36. furi_record_close("bt");
  37. return -1;
  38. }
  39. bool bt_turned_on = furi_hal_bt_is_active();
  40. if(!bt_turned_on) {
  41. furi_hal_bt_start_advertising();
  42. }
  43. osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(BleKeyboardEvent), NULL);
  44. furi_check(event_queue);
  45. ViewPort* view_port = view_port_alloc();
  46. view_port_draw_callback_set(view_port, ble_keyboard_render_callback, NULL);
  47. view_port_input_callback_set(view_port, ble_keyboard_input_callback, event_queue);
  48. // Open GUI and register view_port
  49. Gui* gui = furi_record_open("gui");
  50. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  51. BleKeyboardEvent event;
  52. while(1) {
  53. osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, osWaitForever);
  54. if(event_status == osOK) {
  55. if(event.type == EventTypeInput) {
  56. if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
  57. furi_hal_bt_hid_kb_release_all();
  58. break;
  59. }
  60. if(event.input.key == InputKeyBack) {
  61. if(event.input.type == InputTypePress) {
  62. furi_hal_bt_hid_kb_press(KEY_ESC);
  63. } else if(event.input.type == InputTypeRelease) {
  64. furi_hal_bt_hid_kb_release(KEY_ESC);
  65. }
  66. }
  67. if(event.input.key == InputKeyOk) {
  68. if(event.input.type == InputTypePress) {
  69. furi_hal_bt_hid_kb_press(KEY_ENTER);
  70. } else if(event.input.type == InputTypeRelease) {
  71. furi_hal_bt_hid_kb_release(KEY_ENTER);
  72. }
  73. }
  74. if(event.input.key == InputKeyRight) {
  75. if(event.input.type == InputTypePress) {
  76. furi_hal_bt_hid_kb_press(KEY_RIGHT_ARROW);
  77. } else if(event.input.type == InputTypeRelease) {
  78. furi_hal_bt_hid_kb_release(KEY_RIGHT_ARROW);
  79. }
  80. }
  81. if(event.input.key == InputKeyLeft) {
  82. if(event.input.type == InputTypePress) {
  83. furi_hal_bt_hid_kb_press(KEY_LEFT_ARROW);
  84. } else if(event.input.type == InputTypeRelease) {
  85. furi_hal_bt_hid_kb_release(KEY_LEFT_ARROW);
  86. }
  87. }
  88. if(event.input.key == InputKeyDown) {
  89. if(event.input.type == InputTypePress) {
  90. furi_hal_bt_hid_kb_press(KEY_DOWN_ARROW);
  91. } else if(event.input.type == InputTypeRelease) {
  92. furi_hal_bt_hid_kb_release(KEY_DOWN_ARROW);
  93. }
  94. }
  95. if(event.input.key == InputKeyUp) {
  96. if(event.input.type == InputTypePress) {
  97. furi_hal_bt_hid_kb_press(KEY_UP_ARROW);
  98. } else if(event.input.type == InputTypeRelease) {
  99. furi_hal_bt_hid_kb_release(KEY_UP_ARROW);
  100. }
  101. }
  102. }
  103. }
  104. view_port_update(view_port);
  105. }
  106. if(bt_turned_on) {
  107. furi_hal_bt_stop_advertising();
  108. }
  109. // remove & free all stuff created by app
  110. gui_remove_view_port(gui, view_port);
  111. view_port_free(view_port);
  112. osMessageQueueDelete(event_queue);
  113. furi_record_close("gui");
  114. bt_set_profile(bt, BtProfileSerial);
  115. furi_record_close("bt");
  116. return 0;
  117. }