From 1bcec4be18752f47471107a90c163dba49139918 Mon Sep 17 00:00:00 2001 From: Kai Krakow Date: Sun, 28 Mar 2021 16:36:56 +0200 Subject: [PATCH] [WIP] xpadneo, mouse: Implement mouse support Co-authored-by: Jacob Essex Co-authored-by: Florian Dollinger Closes: https://github.com/atar-axis/xpadneo/pull/160 Closes: https://github.com/atar-axis/xpadneo/pull/105 Closes: https://github.com/atar-axis/xpadneo/issues/99 Signed-off-by: Kai Krakow --- hid-xpadneo/src/hid-xpadneo.c | 78 ++++++++++++++++++++++++++++++++++- hid-xpadneo/src/xpadneo.h | 7 +++- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/hid-xpadneo/src/hid-xpadneo.c b/hid-xpadneo/src/hid-xpadneo.c index ea8ba740..f6d088d2 100644 --- a/hid-xpadneo/src/hid-xpadneo.c +++ b/hid-xpadneo/src/hid-xpadneo.c @@ -749,7 +749,10 @@ static u8 *xpadneo_report_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int static void xpadneo_toggle_mouse(struct xpadneo_devdata *xdata) { - if (xdata->mouse_mode) { + if (!xdata->mouse) { + xdata->mouse_mode = false; + hid_info(xdata->hdev, "mouse not available\n"); + } else if (xdata->mouse_mode) { xdata->mouse_mode = false; hid_info(xdata->hdev, "mouse mode disabled\n"); } else { @@ -889,6 +892,7 @@ static int xpadneo_input_configured(struct hid_device *hdev, struct hid_input *h return 0; default: hid_warn(hdev, "unhandled input application 0x%x\n", hi->application); + return 0; } /* @@ -970,6 +974,20 @@ static int xpadneo_input_configured(struct hid_device *hdev, struct hid_input *h return 0; } +static void xpadneo_mouse_event(struct timer_list *t) +{ + struct xpadneo_devdata *xdata = from_timer(xdata, t, mouse_timer); + struct input_dev *mouse = xdata->mouse; + + if (xdata->mouse_mode) { + input_report_rel(mouse, REL_X, xdata->mouse_state.rel_x / 2000); + input_report_rel(mouse, REL_Y, xdata->mouse_state.rel_y / 2000); + input_sync(xdata->mouse); + } + + mod_timer(&xdata->mouse_timer, jiffies + msecs_to_jiffies(10)); +} + static int xpadneo_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { @@ -977,7 +995,16 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field, struct input_dev *gamepad = xdata->gamepad; struct input_dev *consumer = xdata->consumer; - if (usage->type == EV_ABS) { + if (xdata->mouse_mode && usage->type == EV_ABS) { + switch (usage->code) { + case ABS_X: + xdata->mouse_state.rel_x = value - 32768; + break; + case ABS_Y: + xdata->mouse_state.rel_y = value - 32768; + break; + } + } else if (usage->type == EV_ABS) { switch (usage->code) { case ABS_X: case ABS_Y: @@ -1191,6 +1218,43 @@ static int xpadneo_init_synthetic(struct xpadneo_devdata *xdata, char *suffix, return 0; } +static int xpadneo_init_mouse(struct xpadneo_devdata *xdata) +{ + struct hid_device *hdev = xdata->hdev; + int ret; + + ret = xpadneo_init_synthetic(xdata, "Mouse", &xdata->mouse); + if (ret || !xdata->mouse) + return ret; + + /* enable relative events for mouse emulation */ + __set_bit(EV_REL, xdata->mouse->evbit); + __set_bit(REL_X, xdata->mouse->relbit); + __set_bit(REL_Y, xdata->mouse->relbit); + __set_bit(REL_HWHEEL, xdata->mouse->relbit); + __set_bit(REL_WHEEL, xdata->mouse->relbit); + + /* enable button events for mouse emulation */ + __set_bit(EV_KEY, xdata->mouse->evbit); + __set_bit(BTN_LEFT, xdata->mouse->keybit); + __set_bit(BTN_RIGHT, xdata->mouse->keybit); + __set_bit(BTN_MIDDLE, xdata->mouse->keybit); + __set_bit(BTN_SIDE, xdata->mouse->keybit); + __set_bit(BTN_EXTRA, xdata->mouse->keybit); + __set_bit(BTN_FORWARD, xdata->mouse->keybit); + __set_bit(BTN_BACK, xdata->mouse->keybit); + __set_bit(BTN_TASK, xdata->mouse->keybit); + + ret = input_register_device(xdata->mouse); + if (ret) { + hid_err(hdev, "failed to register mouse\n"); + return ret; + } + + hid_info(hdev, "mouse added\n"); + return 0; +} + static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; @@ -1219,6 +1283,12 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id return ret; } + if (!xdata->mouse) { + ret = xpadneo_init_mouse(xdata); + if (ret) + return ret; + } + ret = xpadneo_init_hw(hdev); if (ret) { hid_err(hdev, "hw init failed: %d\n", ret); @@ -1230,6 +1300,9 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id if (ret) hid_err(hdev, "could not initialize ff, continuing anyway\n"); + timer_setup(&xdata->mouse_timer, xpadneo_mouse_event, 0); + mod_timer(&xdata->mouse_timer, jiffies); + hid_info(hdev, "%s connected\n", xdata->battery.name); return 0; @@ -1249,6 +1322,7 @@ static void xpadneo_remove(struct hid_device *hdev) hid_hw_close(hdev); + del_timer_sync(&xdata->mouse_timer); cancel_delayed_work_sync(&xdata->ff_worker); kfree(xdata->battery.name); diff --git a/hid-xpadneo/src/xpadneo.h b/hid-xpadneo/src/xpadneo.h index f4292613..aa12e432 100644 --- a/hid-xpadneo/src/xpadneo.h +++ b/hid-xpadneo/src/xpadneo.h @@ -12,6 +12,7 @@ #define XPADNEO_H_FILE #include +#include #include #include "hid-ids.h" @@ -125,7 +126,7 @@ struct xpadneo_devdata { /* logical device interfaces */ struct hid_device *hdev; - struct input_dev *consumer, *gamepad, *keyboard; + struct input_dev *consumer, *gamepad, *keyboard, *mouse; short int missing_reported; /* quirk flags */ @@ -138,6 +139,10 @@ struct xpadneo_devdata { /* mouse mode */ bool mouse_mode; + struct timer_list mouse_timer; + struct { + s32 rel_x, rel_y, wheel_x, wheel_y; + } mouse_state; /* trigger scale */ struct {