mirror of https://github.com/Genymobile/scrcpy
Add AOA gamepad support
Similar to AOA keyboard and mouse, but for gamepads. Can be enabled with --gamepad=aoa. PR #5270 <https://github.com/Genymobile/scrcpy/pull/5270>
This commit is contained in:
parent
a59c6df4b7
commit
a34a62ca4b
|
@ -26,6 +26,7 @@ _scrcpy() {
|
||||||
-e --select-tcpip
|
-e --select-tcpip
|
||||||
-f --fullscreen
|
-f --fullscreen
|
||||||
--force-adb-forward
|
--force-adb-forward
|
||||||
|
--gamepad=
|
||||||
-h --help
|
-h --help
|
||||||
-K
|
-K
|
||||||
--keyboard=
|
--keyboard=
|
||||||
|
@ -127,6 +128,10 @@ _scrcpy() {
|
||||||
COMPREPLY=($(compgen -W 'disabled sdk uhid aoa' -- "$cur"))
|
COMPREPLY=($(compgen -W 'disabled sdk uhid aoa' -- "$cur"))
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--gamepad)
|
||||||
|
COMPREPLY=($(compgen -W 'disabled aoa' -- "$cur"))
|
||||||
|
return
|
||||||
|
;;
|
||||||
--orientation|--display-orientation)
|
--orientation|--display-orientation)
|
||||||
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
COMPREPLY=($(compgen -W '0 90 180 270 flip0 flip90 flip180 flip270' -- "$cur"))
|
||||||
return
|
return
|
||||||
|
|
|
@ -33,6 +33,7 @@ arguments=(
|
||||||
{-e,--select-tcpip}'[Use TCP/IP device]'
|
{-e,--select-tcpip}'[Use TCP/IP device]'
|
||||||
{-f,--fullscreen}'[Start in fullscreen]'
|
{-f,--fullscreen}'[Start in fullscreen]'
|
||||||
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
|
'--force-adb-forward[Do not attempt to use \"adb reverse\" to connect to the device]'
|
||||||
|
'--gamepad=[Set the gamepad input mode]:mode:(disabled aoa)'
|
||||||
{-h,--help}'[Print the help]'
|
{-h,--help}'[Print the help]'
|
||||||
'-K[Use UHID keyboard (same as --keyboard=uhid)]'
|
'-K[Use UHID keyboard (same as --keyboard=uhid)]'
|
||||||
'--keyboard=[Set the keyboard input mode]:mode:(disabled sdk uhid aoa)'
|
'--keyboard=[Set the keyboard input mode]:mode:(disabled sdk uhid aoa)'
|
||||||
|
|
|
@ -95,6 +95,7 @@ usb_support = get_option('usb')
|
||||||
if usb_support
|
if usb_support
|
||||||
src += [
|
src += [
|
||||||
'src/usb/aoa_hid.c',
|
'src/usb/aoa_hid.c',
|
||||||
|
'src/usb/gamepad_aoa.c',
|
||||||
'src/usb/keyboard_aoa.c',
|
'src/usb/keyboard_aoa.c',
|
||||||
'src/usb/mouse_aoa.c',
|
'src/usb/mouse_aoa.c',
|
||||||
'src/usb/scrcpy_otg.c',
|
'src/usb/scrcpy_otg.c',
|
||||||
|
|
16
app/scrcpy.1
16
app/scrcpy.1
|
@ -175,6 +175,16 @@ Start in fullscreen.
|
||||||
.B \-\-force\-adb\-forward
|
.B \-\-force\-adb\-forward
|
||||||
Do not attempt to use "adb reverse" to connect to the device.
|
Do not attempt to use "adb reverse" to connect to the device.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "\-\-gamepad " mode
|
||||||
|
Select how to send gamepad inputs to the device.
|
||||||
|
|
||||||
|
Possible values are "disabled" and "aoa":
|
||||||
|
|
||||||
|
- "disabled" does not send gamepad inputs to the device.
|
||||||
|
- "aoa" simulates physical HID gamepads using the AOAv2 protocol. It may only work over USB.
|
||||||
|
|
||||||
|
Also see \fB\-\-keyboard\f and R\fB\-\-mouse\fR.
|
||||||
.TP
|
.TP
|
||||||
.B \-h, \-\-help
|
.B \-h, \-\-help
|
||||||
Print this help.
|
Print this help.
|
||||||
|
@ -200,7 +210,7 @@ For "uhid" and "aoa", the keyboard layout must be configured (once and for all)
|
||||||
|
|
||||||
This option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
This option is only available when the HID keyboard is enabled (or a physical keyboard is connected).
|
||||||
|
|
||||||
Also see \fB\-\-mouse\fR.
|
Also see \fB\-\-mouse\fR and \fB\-\-gamepad\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-\-kill\-adb\-on\-close
|
.B \-\-kill\-adb\-on\-close
|
||||||
|
@ -267,7 +277,7 @@ In "uhid" and "aoa" modes, the computer mouse is captured to control the device
|
||||||
|
|
||||||
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
|
LAlt, LSuper or RSuper toggle the capture mode, to give control of the mouse back to the computer.
|
||||||
|
|
||||||
Also see \fB\-\-keyboard\fR.
|
Also see \fB\-\-keyboard\fR and \fB\-\-gamepad\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-mouse\-bind " xxxx[:xxxx]
|
.BI "\-\-mouse\-bind " xxxx[:xxxx]
|
||||||
|
@ -369,7 +379,7 @@ If any of \fB\-\-hid\-keyboard\fR or \fB\-\-hid\-mouse\fR is set, only enable ke
|
||||||
|
|
||||||
It may only work over USB.
|
It may only work over USB.
|
||||||
|
|
||||||
See \fB\-\-keyboard\fR and \fB\-\-mouse\fR.
|
See \fB\-\-keyboard\fR, \fB\-\-mouse\fR and \fB\-\-gamepad\fR.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "\-p, \-\-port " port\fR[:\fIport\fR]
|
.BI "\-p, \-\-port " port\fR[:\fIport\fR]
|
||||||
|
|
|
@ -101,6 +101,7 @@ enum {
|
||||||
OPT_MOUSE_BIND,
|
OPT_MOUSE_BIND,
|
||||||
OPT_NO_MOUSE_HOVER,
|
OPT_NO_MOUSE_HOVER,
|
||||||
OPT_AUDIO_DUP,
|
OPT_AUDIO_DUP,
|
||||||
|
OPT_GAMEPAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_option {
|
struct sc_option {
|
||||||
|
@ -372,6 +373,17 @@ static const struct sc_option options[] = {
|
||||||
.longopt_id = OPT_FORWARD_ALL_CLICKS,
|
.longopt_id = OPT_FORWARD_ALL_CLICKS,
|
||||||
.longopt = "forward-all-clicks",
|
.longopt = "forward-all-clicks",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.longopt_id = OPT_GAMEPAD,
|
||||||
|
.longopt = "gamepad",
|
||||||
|
.argdesc = "mode",
|
||||||
|
.text = "Select how to send gamepad inputs to the device.\n"
|
||||||
|
"Possible values are \"disabled\" and \"aoa\".\n"
|
||||||
|
"\"disabled\" does not send gamepad inputs to the device.\n"
|
||||||
|
"\"aoa\" simulates physical gamepads using the AOAv2 protocol."
|
||||||
|
"It may only work over USB.\n"
|
||||||
|
"Also see --keyboard and --mouse.",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'h',
|
.shortopt = 'h',
|
||||||
.longopt = "help",
|
.longopt = "help",
|
||||||
|
@ -403,7 +415,7 @@ static const struct sc_option options[] = {
|
||||||
"start -a android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
"start -a android.settings.HARD_KEYBOARD_SETTINGS`.\n"
|
||||||
"This option is only available when a HID keyboard is enabled "
|
"This option is only available when a HID keyboard is enabled "
|
||||||
"(or a physical keyboard is connected).\n"
|
"(or a physical keyboard is connected).\n"
|
||||||
"Also see --mouse.",
|
"Also see --mouse and --gamepad.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_KILL_ADB_ON_CLOSE,
|
.longopt_id = OPT_KILL_ADB_ON_CLOSE,
|
||||||
|
@ -502,7 +514,7 @@ static const struct sc_option options[] = {
|
||||||
"to control the device directly (relative mouse mode).\n"
|
"to control the device directly (relative mouse mode).\n"
|
||||||
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
"LAlt, LSuper or RSuper toggle the capture mode, to give "
|
||||||
"control of the mouse back to the computer.\n"
|
"control of the mouse back to the computer.\n"
|
||||||
"Also see --keyboard.",
|
"Also see --keyboard and --gamepad.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.longopt_id = OPT_MOUSE_BIND,
|
.longopt_id = OPT_MOUSE_BIND,
|
||||||
|
@ -637,7 +649,7 @@ static const struct sc_option options[] = {
|
||||||
"Keyboard and mouse may be disabled separately using"
|
"Keyboard and mouse may be disabled separately using"
|
||||||
"--keyboard=disabled and --mouse=disabled.\n"
|
"--keyboard=disabled and --mouse=disabled.\n"
|
||||||
"It may only work over USB.\n"
|
"It may only work over USB.\n"
|
||||||
"See --keyboard and --mouse.",
|
"See --keyboard, --mouse and --gamepad.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.shortopt = 'p',
|
.shortopt = 'p',
|
||||||
|
@ -2046,6 +2058,27 @@ parse_mouse(const char *optarg, enum sc_mouse_input_mode *mode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_gamepad(const char *optarg, enum sc_gamepad_input_mode *mode) {
|
||||||
|
if (!strcmp(optarg, "disabled")) {
|
||||||
|
*mode = SC_GAMEPAD_INPUT_MODE_DISABLED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "aoa")) {
|
||||||
|
#ifdef HAVE_USB
|
||||||
|
*mode = SC_GAMEPAD_INPUT_MODE_AOA;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
LOGE("--gamepad=aoa is disabled.");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGE("Unsupported gamepad: %s (expected disabled or aoa)", optarg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
parse_time_limit(const char *s, sc_tick *tick) {
|
parse_time_limit(const char *s, sc_tick *tick) {
|
||||||
long value;
|
long value;
|
||||||
|
@ -2612,6 +2645,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
|
||||||
case OPT_AUDIO_DUP:
|
case OPT_AUDIO_DUP:
|
||||||
opts->audio_dup = true;
|
opts->audio_dup = true;
|
||||||
break;
|
break;
|
||||||
|
case OPT_GAMEPAD:
|
||||||
|
if (!parse_gamepad(optarg, &opts->gamepad_input_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// getopt prints the error message on stderr
|
// getopt prints the error message on stderr
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -23,6 +23,7 @@ const struct scrcpy_options scrcpy_options_default = {
|
||||||
.record_format = SC_RECORD_FORMAT_AUTO,
|
.record_format = SC_RECORD_FORMAT_AUTO,
|
||||||
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
.keyboard_input_mode = SC_KEYBOARD_INPUT_MODE_AUTO,
|
||||||
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
.mouse_input_mode = SC_MOUSE_INPUT_MODE_AUTO,
|
||||||
|
.gamepad_input_mode = SC_GAMEPAD_INPUT_MODE_DISABLED,
|
||||||
.mouse_bindings = {
|
.mouse_bindings = {
|
||||||
.pri = {
|
.pri = {
|
||||||
.right_click = SC_MOUSE_BINDING_AUTO,
|
.right_click = SC_MOUSE_BINDING_AUTO,
|
||||||
|
|
|
@ -156,6 +156,11 @@ enum sc_mouse_input_mode {
|
||||||
SC_MOUSE_INPUT_MODE_AOA,
|
SC_MOUSE_INPUT_MODE_AOA,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sc_gamepad_input_mode {
|
||||||
|
SC_GAMEPAD_INPUT_MODE_DISABLED,
|
||||||
|
SC_GAMEPAD_INPUT_MODE_AOA,
|
||||||
|
};
|
||||||
|
|
||||||
enum sc_mouse_binding {
|
enum sc_mouse_binding {
|
||||||
SC_MOUSE_BINDING_AUTO,
|
SC_MOUSE_BINDING_AUTO,
|
||||||
SC_MOUSE_BINDING_DISABLED,
|
SC_MOUSE_BINDING_DISABLED,
|
||||||
|
@ -231,6 +236,7 @@ struct scrcpy_options {
|
||||||
enum sc_record_format record_format;
|
enum sc_record_format record_format;
|
||||||
enum sc_keyboard_input_mode keyboard_input_mode;
|
enum sc_keyboard_input_mode keyboard_input_mode;
|
||||||
enum sc_mouse_input_mode mouse_input_mode;
|
enum sc_mouse_input_mode mouse_input_mode;
|
||||||
|
enum sc_gamepad_input_mode gamepad_input_mode;
|
||||||
struct sc_mouse_bindings mouse_bindings;
|
struct sc_mouse_bindings mouse_bindings;
|
||||||
enum sc_camera_facing camera_facing;
|
enum sc_camera_facing camera_facing;
|
||||||
struct sc_port_range port_range;
|
struct sc_port_range port_range;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "uhid/mouse_uhid.h"
|
#include "uhid/mouse_uhid.h"
|
||||||
#ifdef HAVE_USB
|
#ifdef HAVE_USB
|
||||||
# include "usb/aoa_hid.h"
|
# include "usb/aoa_hid.h"
|
||||||
|
# include "usb/gamepad_aoa.h"
|
||||||
# include "usb/keyboard_aoa.h"
|
# include "usb/keyboard_aoa.h"
|
||||||
# include "usb/mouse_aoa.h"
|
# include "usb/mouse_aoa.h"
|
||||||
# include "usb/usb.h"
|
# include "usb/usb.h"
|
||||||
|
@ -79,6 +80,9 @@ struct scrcpy {
|
||||||
struct sc_mouse_aoa mouse_aoa;
|
struct sc_mouse_aoa mouse_aoa;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
#ifdef HAVE_USB
|
||||||
|
struct sc_gamepad_aoa gamepad_aoa;
|
||||||
|
#endif
|
||||||
struct sc_timeout timeout;
|
struct sc_timeout timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -370,6 +374,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
bool aoa_hid_initialized = false;
|
bool aoa_hid_initialized = false;
|
||||||
bool keyboard_aoa_initialized = false;
|
bool keyboard_aoa_initialized = false;
|
||||||
bool mouse_aoa_initialized = false;
|
bool mouse_aoa_initialized = false;
|
||||||
|
bool gamepad_aoa_initialized = false;
|
||||||
#endif
|
#endif
|
||||||
bool controller_initialized = false;
|
bool controller_initialized = false;
|
||||||
bool controller_started = false;
|
bool controller_started = false;
|
||||||
|
@ -485,9 +490,11 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER)) {
|
if (options->gamepad_input_mode != SC_GAMEPAD_INPUT_MODE_DISABLED) {
|
||||||
LOGE("Could not initialize SDL gamepad: %s", SDL_GetError());
|
if (SDL_Init(SDL_INIT_GAMECONTROLLER)) {
|
||||||
goto end;
|
LOGE("Could not initialize SDL gamepad: %s", SDL_GetError());
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sdl_configure(options->video_playback, options->disable_screensaver);
|
sdl_configure(options->video_playback, options->disable_screensaver);
|
||||||
|
@ -587,6 +594,7 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
struct sc_controller *controller = NULL;
|
struct sc_controller *controller = NULL;
|
||||||
struct sc_key_processor *kp = NULL;
|
struct sc_key_processor *kp = NULL;
|
||||||
struct sc_mouse_processor *mp = NULL;
|
struct sc_mouse_processor *mp = NULL;
|
||||||
|
struct sc_gamepad_processor *gp = NULL;
|
||||||
|
|
||||||
if (options->control) {
|
if (options->control) {
|
||||||
static const struct sc_controller_callbacks controller_cbs = {
|
static const struct sc_controller_callbacks controller_cbs = {
|
||||||
|
@ -606,7 +614,9 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
options->keyboard_input_mode == SC_KEYBOARD_INPUT_MODE_AOA;
|
||||||
bool use_mouse_aoa =
|
bool use_mouse_aoa =
|
||||||
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
options->mouse_input_mode == SC_MOUSE_INPUT_MODE_AOA;
|
||||||
if (use_keyboard_aoa || use_mouse_aoa) {
|
bool use_gamepad_aoa =
|
||||||
|
options->gamepad_input_mode == SC_GAMEPAD_INPUT_MODE_AOA;
|
||||||
|
if (use_keyboard_aoa || use_mouse_aoa || use_gamepad_aoa) {
|
||||||
bool ok = sc_acksync_init(&s->acksync);
|
bool ok = sc_acksync_init(&s->acksync);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -672,6 +682,12 @@ scrcpy(struct scrcpy_options *options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_gamepad_aoa) {
|
||||||
|
sc_gamepad_aoa_init(&s->gamepad_aoa, &s->aoa);
|
||||||
|
gp = &s->gamepad_aoa.gamepad_processor;
|
||||||
|
gamepad_aoa_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
aoa_complete:
|
aoa_complete:
|
||||||
if (aoa_fail || !sc_aoa_start(&s->aoa)) {
|
if (aoa_fail || !sc_aoa_start(&s->aoa)) {
|
||||||
sc_acksync_destroy(&s->acksync);
|
sc_acksync_destroy(&s->acksync);
|
||||||
|
@ -740,7 +756,7 @@ aoa_complete:
|
||||||
.fp = fp,
|
.fp = fp,
|
||||||
.kp = kp,
|
.kp = kp,
|
||||||
.mp = mp,
|
.mp = mp,
|
||||||
.gp = NULL,
|
.gp = gp,
|
||||||
.mouse_bindings = options->mouse_bindings,
|
.mouse_bindings = options->mouse_bindings,
|
||||||
.legacy_paste = options->legacy_paste,
|
.legacy_paste = options->legacy_paste,
|
||||||
.clipboard_autosync = options->clipboard_autosync,
|
.clipboard_autosync = options->clipboard_autosync,
|
||||||
|
@ -878,6 +894,9 @@ end:
|
||||||
if (mouse_aoa_initialized) {
|
if (mouse_aoa_initialized) {
|
||||||
sc_mouse_aoa_destroy(&s->mouse_aoa);
|
sc_mouse_aoa_destroy(&s->mouse_aoa);
|
||||||
}
|
}
|
||||||
|
if (gamepad_aoa_initialized) {
|
||||||
|
sc_gamepad_aoa_destroy(&s->gamepad_aoa);
|
||||||
|
}
|
||||||
sc_aoa_stop(&s->aoa);
|
sc_aoa_stop(&s->aoa);
|
||||||
sc_usb_stop(&s->usb);
|
sc_usb_stop(&s->usb);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include "gamepad_aoa.h"
|
||||||
|
|
||||||
|
#include "input_events.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
/** Downcast gamepad processor to gamepad_aoa */
|
||||||
|
#define DOWNCAST(GP) container_of(GP, struct sc_gamepad_aoa, gamepad_processor)
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_device_event *event) {
|
||||||
|
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
|
if (event->type == SC_GAMEPAD_DEVICE_ADDED) {
|
||||||
|
struct sc_hid_open hid_open;
|
||||||
|
if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open,
|
||||||
|
event->gamepad_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit_on_error: false (a gamepad open failure should not exit scrcpy)
|
||||||
|
if (!sc_aoa_push_open(gamepad->aoa, &hid_open, false)) {
|
||||||
|
LOGW("Could not push AOA HID open (gamepad)");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(event->type == SC_GAMEPAD_DEVICE_REMOVED);
|
||||||
|
|
||||||
|
struct sc_hid_close hid_close;
|
||||||
|
if (!sc_hid_gamepad_generate_close(&gamepad->hid, &hid_close,
|
||||||
|
event->gamepad_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sc_aoa_push_close(gamepad->aoa, &hid_close)) {
|
||||||
|
LOGW("Could not push AOA HID close (gamepad)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_gamepad_processor_process_gamepad_axis(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_axis_event *event) {
|
||||||
|
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
|
struct sc_hid_input hid_input;
|
||||||
|
if (!sc_hid_gamepad_generate_input_from_axis(&gamepad->hid, &hid_input,
|
||||||
|
event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sc_aoa_push_input(gamepad->aoa, &hid_input)) {
|
||||||
|
LOGW("Could not push AOA HID input (gamepad axis)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_gamepad_processor_process_gamepad_button(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_button_event *event) {
|
||||||
|
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
|
struct sc_hid_input hid_input;
|
||||||
|
if (!sc_hid_gamepad_generate_input_from_button(&gamepad->hid, &hid_input,
|
||||||
|
event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sc_aoa_push_input(gamepad->aoa, &hid_input)) {
|
||||||
|
LOGW("Could not push AOA HID input (gamepad button)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_gamepad_aoa_init(struct sc_gamepad_aoa *gamepad, struct sc_aoa *aoa) {
|
||||||
|
gamepad->aoa = aoa;
|
||||||
|
|
||||||
|
sc_hid_gamepad_init(&gamepad->hid);
|
||||||
|
|
||||||
|
static const struct sc_gamepad_processor_ops ops = {
|
||||||
|
.process_gamepad_device = sc_gamepad_processor_process_gamepad_device,
|
||||||
|
.process_gamepad_axis = sc_gamepad_processor_process_gamepad_axis,
|
||||||
|
.process_gamepad_button = sc_gamepad_processor_process_gamepad_button,
|
||||||
|
};
|
||||||
|
|
||||||
|
gamepad->gamepad_processor.ops = &ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_gamepad_aoa_destroy(struct sc_gamepad_aoa *gamepad) {
|
||||||
|
(void) gamepad;
|
||||||
|
// Do nothing, gamepad->aoa will automatically unregister all devices
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef SC_GAMEPAD_AOA_H
|
||||||
|
#define SC_GAMEPAD_AOA_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "aoa_hid.h"
|
||||||
|
#include "hid/hid_gamepad.h"
|
||||||
|
#include "trait/gamepad_processor.h"
|
||||||
|
|
||||||
|
struct sc_gamepad_aoa {
|
||||||
|
struct sc_gamepad_processor gamepad_processor; // gamepad processor trait
|
||||||
|
|
||||||
|
struct sc_hid_gamepad hid;
|
||||||
|
struct sc_aoa *aoa;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_gamepad_aoa_init(struct sc_gamepad_aoa *gamepad, struct sc_aoa *aoa);
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_gamepad_aoa_destroy(struct sc_gamepad_aoa *gamepad);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue