-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
359 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
#include "xbox_controller_view.h" | ||
#include <furi.h> | ||
#include <furi_hal_usb_hid.h> | ||
#include <gui/elements.h> | ||
#include <xc_icons.h> | ||
|
||
struct XboxControllerView { | ||
View* view; | ||
}; | ||
|
||
typedef struct { | ||
bool left_pressed; | ||
bool up_pressed; | ||
bool right_pressed; | ||
bool down_pressed; | ||
bool ok_pressed; | ||
bool back_pressed; | ||
bool connected; | ||
} XboxControllerViewModel; | ||
|
||
static void | ||
xbox_controller_view_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { | ||
canvas_draw_triangle(canvas, x, y, 5, 3, dir); | ||
if(dir == CanvasDirectionBottomToTop) { | ||
canvas_draw_line(canvas, x, y + 6, x, y - 1); | ||
} else if(dir == CanvasDirectionTopToBottom) { | ||
canvas_draw_line(canvas, x, y - 6, x, y + 1); | ||
} else if(dir == CanvasDirectionRightToLeft) { | ||
canvas_draw_line(canvas, x + 6, y, x - 1, y); | ||
} else if(dir == CanvasDirectionLeftToRight) { | ||
canvas_draw_line(canvas, x - 6, y, x + 1, y); | ||
} | ||
} | ||
|
||
static void xbox_controller_view_draw_callback(Canvas* canvas, void* context) { | ||
furi_assert(context); | ||
XboxControllerViewModel* model = context; | ||
|
||
canvas_set_font(canvas, FontPrimary); | ||
elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Xbox One"); | ||
|
||
canvas_draw_icon(canvas, 54, 0, &I_Pin_back_arrow_10x8); | ||
canvas_set_font(canvas, FontSecondary); | ||
elements_multiline_text_aligned(canvas, 127, 1, AlignRight, AlignTop, "Hold to change"); | ||
|
||
// Up | ||
canvas_draw_icon(canvas, 21, 24, &I_Button_18x18); | ||
if(model->up_pressed) { | ||
elements_slightly_rounded_box(canvas, 24, 26, 13, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
xbox_controller_view_draw_arrow(canvas, 30, 30, CanvasDirectionBottomToTop); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Down | ||
canvas_draw_icon(canvas, 21, 45, &I_Button_18x18); | ||
if(model->down_pressed) { | ||
elements_slightly_rounded_box(canvas, 24, 47, 13, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
xbox_controller_view_draw_arrow(canvas, 30, 55, CanvasDirectionTopToBottom); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Left | ||
canvas_draw_icon(canvas, 0, 45, &I_Button_18x18); | ||
if(model->left_pressed) { | ||
elements_slightly_rounded_box(canvas, 3, 47, 13, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
xbox_controller_view_draw_arrow(canvas, 7, 53, CanvasDirectionRightToLeft); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Right | ||
canvas_draw_icon(canvas, 42, 45, &I_Button_18x18); | ||
if(model->right_pressed) { | ||
elements_slightly_rounded_box(canvas, 45, 47, 13, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
xbox_controller_view_draw_arrow(canvas, 53, 53, CanvasDirectionLeftToRight); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Ok | ||
canvas_draw_icon(canvas, 63, 25, &I_Space_65x18); | ||
if(model->ok_pressed) { | ||
elements_slightly_rounded_box(canvas, 66, 27, 60, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
canvas_draw_icon(canvas, 74, 29, &I_Ok_btn_9x9); | ||
elements_multiline_text_aligned(canvas, 91, 36, AlignLeft, AlignBottom, "A"); | ||
canvas_set_color(canvas, ColorBlack); | ||
|
||
// Back | ||
canvas_draw_icon(canvas, 63, 45, &I_Space_65x18); | ||
if(model->back_pressed) { | ||
elements_slightly_rounded_box(canvas, 66, 47, 60, 13); | ||
canvas_set_color(canvas, ColorWhite); | ||
} | ||
canvas_draw_icon(canvas, 74, 49, &I_Pin_back_arrow_10x8); | ||
elements_multiline_text_aligned(canvas, 91, 57, AlignLeft, AlignBottom, "B"); | ||
} | ||
|
||
static void | ||
xbox_controller_view_process(XboxControllerView* xbox_controller_view, InputEvent* event) { | ||
with_view_model( | ||
xbox_controller_view->view, | ||
XboxControllerViewModel * model, | ||
{ | ||
if(event->type == InputTypePress) { | ||
if(event->key == InputKeyUp) { | ||
model->up_pressed = true; | ||
furi_hal_hid_kb_press(HID_KEYBOARD_UP_ARROW); | ||
} else if(event->key == InputKeyDown) { | ||
model->down_pressed = true; | ||
furi_hal_hid_kb_press(HID_KEYBOARD_DOWN_ARROW); | ||
} else if(event->key == InputKeyLeft) { | ||
model->left_pressed = true; | ||
furi_hal_hid_kb_press(HID_KEYBOARD_LEFT_ARROW); | ||
} else if(event->key == InputKeyRight) { | ||
model->right_pressed = true; | ||
furi_hal_hid_kb_press(HID_KEYBOARD_RIGHT_ARROW); | ||
} else if(event->key == InputKeyOk) { | ||
model->ok_pressed = true; | ||
furi_hal_hid_kb_press(HID_KEYBOARD_SPACEBAR); | ||
} else if(event->key == InputKeyBack) { | ||
model->back_pressed = true; | ||
} | ||
} else if(event->type == InputTypeRelease) { | ||
if(event->key == InputKeyUp) { | ||
model->up_pressed = false; | ||
furi_hal_hid_kb_release(HID_KEYBOARD_UP_ARROW); | ||
} else if(event->key == InputKeyDown) { | ||
model->down_pressed = false; | ||
furi_hal_hid_kb_release(HID_KEYBOARD_DOWN_ARROW); | ||
} else if(event->key == InputKeyLeft) { | ||
model->left_pressed = false; | ||
furi_hal_hid_kb_release(HID_KEYBOARD_LEFT_ARROW); | ||
} else if(event->key == InputKeyRight) { | ||
model->right_pressed = false; | ||
furi_hal_hid_kb_release(HID_KEYBOARD_RIGHT_ARROW); | ||
} else if(event->key == InputKeyOk) { | ||
model->ok_pressed = false; | ||
furi_hal_hid_kb_release(HID_KEYBOARD_SPACEBAR); | ||
} else if(event->key == InputKeyBack) { | ||
model->back_pressed = false; | ||
} | ||
} else if(event->type == InputTypeShort) { | ||
if(event->key == InputKeyBack) { | ||
furi_hal_hid_kb_press(HID_KEYBOARD_DELETE); | ||
furi_hal_hid_kb_release(HID_KEYBOARD_DELETE); | ||
furi_hal_hid_consumer_key_press(HID_CONSUMER_AC_BACK); | ||
furi_hal_hid_consumer_key_release(HID_CONSUMER_AC_BACK); | ||
} | ||
} | ||
}, | ||
true); | ||
} | ||
|
||
static bool xbox_controller_view_input_callback(InputEvent* event, void* context) { | ||
furi_assert(context); | ||
XboxControllerView* xbox_controller_view = context; | ||
bool consumed = false; | ||
|
||
if(event->type == InputTypeLong && event->key == InputKeyBack) { | ||
furi_hal_hid_kb_release_all(); | ||
} else { | ||
xbox_controller_view_process(xbox_controller_view, event); | ||
consumed = true; | ||
} | ||
|
||
return consumed; | ||
} | ||
|
||
XboxControllerView* xbox_controller_view_alloc() { | ||
XboxControllerView* xbox_controller_view = malloc(sizeof(XboxControllerView)); | ||
xbox_controller_view->view = view_alloc(); | ||
view_set_context(xbox_controller_view->view, xbox_controller_view); | ||
view_allocate_model( | ||
xbox_controller_view->view, ViewModelTypeLocking, sizeof(XboxControllerViewModel)); | ||
view_set_draw_callback(xbox_controller_view->view, xbox_controller_view_draw_callback); | ||
view_set_input_callback(xbox_controller_view->view, xbox_controller_view_input_callback); | ||
|
||
return xbox_controller_view; | ||
} | ||
|
||
void xbox_controller_view_free(XboxControllerView* xbox_controller_view) { | ||
furi_assert(xbox_controller_view); | ||
view_free(xbox_controller_view->view); | ||
free(xbox_controller_view); | ||
} | ||
|
||
View* xbox_controller_view_get_view(XboxControllerView* xbox_controller_view) { | ||
furi_assert(xbox_controller_view); | ||
return xbox_controller_view->view; | ||
} | ||
|
||
void xbox_controller_view_set_connected_status( | ||
XboxControllerView* xbox_controller_view, | ||
bool connected) { | ||
furi_assert(xbox_controller_view); | ||
with_view_model( | ||
xbox_controller_view->view, | ||
XboxControllerViewModel * model, | ||
{ model->connected = connected; }, | ||
true); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#pragma once | ||
|
||
#include <gui/view.h> | ||
|
||
typedef struct XboxControllerView XboxControllerView; | ||
|
||
XboxControllerView* xbox_controller_view_alloc(); | ||
|
||
void xbox_controller_view_free(XboxControllerView* xbox_controller_view); | ||
|
||
View* xbox_controller_view_get_view(XboxControllerView* xbox_controller_view); | ||
|
||
void xbox_controller_view_set_connected_status( | ||
XboxControllerView* xbox_controller_view, | ||
bool connected); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,132 @@ | ||
#include "xbox_controller.h" | ||
#include "xc_icons.h" | ||
#include <stdio.h> | ||
#include <furi.h> | ||
#include <gui/gui.h> | ||
#include <input/input.h> | ||
#include <notification/notification_messages.h> | ||
|
||
static void draw_callback(Canvas* canvas, void* ctx) { | ||
UNUSED(ctx); | ||
#define TAG "XboxControllerApp" | ||
|
||
canvas_clear(canvas); | ||
canvas_set_font(canvas, FontPrimary); | ||
canvas_draw_str(canvas, 0, 10, "Xbox Controller"); | ||
enum XboxControllerSubmenuIndex { | ||
XboxControllerSubmenuIndexXboxOne, | ||
}; | ||
|
||
uint32_t usb_hid_exit_confirm_view(void* context) { | ||
UNUSED(context); | ||
return UsbHidViewExitConfirm; | ||
} | ||
|
||
static void input_callback(InputEvent* input_event, void* ctx) { | ||
furi_assert(ctx); | ||
FuriMessageQueue* event_queue = ctx; | ||
uint32_t usb_hid_exit(void* context) { | ||
UNUSED(context); | ||
return VIEW_NONE; | ||
} | ||
|
||
furi_message_queue_put(event_queue, input_event, FuriWaitForever); | ||
void usb_hid_submenu_callback(void* context, uint32_t index) { | ||
furi_assert(context); | ||
XboxController* app = context; | ||
if(index == XboxControllerSubmenuIndexXboxOne) { | ||
app->view_id = UsbHidViewXboxController; | ||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewXboxController); | ||
} | ||
} | ||
|
||
int32_t xbox_controller_app(void* p) { | ||
UNUSED(p); | ||
void usb_hid_dialog_callback(DialogExResult result, void* context) { | ||
furi_assert(context); | ||
XboxController* app = context; | ||
if(result == DialogExResultLeft) { | ||
view_dispatcher_stop(app->view_dispatcher); | ||
} else if(result == DialogExResultRight) { | ||
view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); // Show last view | ||
} else if(result == DialogExResultCenter) { | ||
view_dispatcher_switch_to_view(app->view_dispatcher, UsbHidViewSubmenu); | ||
} | ||
} | ||
|
||
InputEvent event; | ||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); | ||
XboxController* xbox_controller_app_alloc() { | ||
XboxController* app = malloc(sizeof(XboxController)); | ||
|
||
ViewPort* view_port = view_port_alloc(); | ||
view_port_draw_callback_set(view_port, draw_callback, NULL); | ||
view_port_input_callback_set(view_port, input_callback, event_queue); | ||
app->gui = furi_record_open(RECORD_GUI); | ||
app->notifications = furi_record_open(RECORD_NOTIFICATION); | ||
app->view_dispatcher = view_dispatcher_alloc(); | ||
|
||
Gui* gui = furi_record_open(RECORD_GUI); | ||
gui_add_view_port(gui, view_port, GuiLayerFullscreen); | ||
view_dispatcher_enable_queue(app->view_dispatcher); | ||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); | ||
|
||
while(1) { | ||
furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk); | ||
// Submenu view | ||
app->submenu = submenu_alloc(); | ||
submenu_add_item( | ||
app->submenu, "Xbox One", XboxControllerSubmenuIndexXboxOne, usb_hid_submenu_callback, app); | ||
view_set_previous_callback(submenu_get_view(app->submenu), usb_hid_exit); | ||
view_dispatcher_add_view( | ||
app->view_dispatcher, UsbHidViewSubmenu, submenu_get_view(app->submenu)); | ||
|
||
if(event.key == InputKeyBack) { | ||
break; | ||
} | ||
} | ||
// Dialog view | ||
app->dialog = dialog_ex_alloc(); | ||
dialog_ex_set_result_callback(app->dialog, usb_hid_dialog_callback); | ||
dialog_ex_set_context(app->dialog, app); | ||
dialog_ex_set_left_button_text(app->dialog, "Exit"); | ||
dialog_ex_set_right_button_text(app->dialog, "Stay"); | ||
dialog_ex_set_center_button_text(app->dialog, "Menu"); | ||
dialog_ex_set_header(app->dialog, "Close Current App?", 16, 12, AlignLeft, AlignTop); | ||
view_dispatcher_add_view( | ||
app->view_dispatcher, UsbHidViewExitConfirm, dialog_ex_get_view(app->dialog)); | ||
|
||
// Dirpad view | ||
app->xbox_controller_view = xbox_controller_view_alloc(); | ||
view_set_previous_callback( | ||
xbox_controller_view_get_view(app->xbox_controller_view), usb_hid_exit_confirm_view); | ||
view_dispatcher_add_view( | ||
app->view_dispatcher, | ||
UsbHidViewXboxController, | ||
xbox_controller_view_get_view(app->xbox_controller_view)); | ||
|
||
// TODO switch to menu after Media is done | ||
app->view_id = UsbHidViewXboxController; | ||
view_dispatcher_switch_to_view(app->view_dispatcher, app->view_id); | ||
|
||
return app; | ||
} | ||
|
||
furi_message_queue_free(event_queue); | ||
void xbox_controller_app_free(XboxController* app) { | ||
furi_assert(app); | ||
|
||
gui_remove_view_port(gui, view_port); | ||
view_port_free(view_port); | ||
// Reset notification | ||
notification_internal_message(app->notifications, &sequence_reset_blue); | ||
|
||
// Free views | ||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewSubmenu); | ||
submenu_free(app->submenu); | ||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewExitConfirm); | ||
dialog_ex_free(app->dialog); | ||
view_dispatcher_remove_view(app->view_dispatcher, UsbHidViewXboxController); | ||
xbox_controller_view_free(app->xbox_controller_view); | ||
view_dispatcher_free(app->view_dispatcher); | ||
|
||
// Close records | ||
furi_record_close(RECORD_GUI); | ||
app->gui = NULL; | ||
furi_record_close(RECORD_NOTIFICATION); | ||
app->notifications = NULL; | ||
|
||
// Free rest | ||
free(app); | ||
} | ||
|
||
int32_t xbox_controller_app(void* p) { | ||
UNUSED(p); | ||
|
||
XboxController* app = xbox_controller_app_alloc(); | ||
|
||
// FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); | ||
// furi_hal_usb_unlock(); | ||
// furi_check(furi_hal_usb_set_config(&usb_hid, NULL) == true); | ||
|
||
view_dispatcher_run(app->view_dispatcher); | ||
|
||
// Change back profile | ||
// furi_hal_usb_set_config(usb_mode_prev, NULL); | ||
xbox_controller_app_free(app); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.