Skip to content

Commit

Permalink
[WIP] xpadneo, mouse: Implement mouse support
Browse files Browse the repository at this point in the history
Co-authored-by: Jacob Essex <[email protected]>
Co-authored-by: Florian Dollinger <[email protected]>
Closes: #160
Closes: #105
Closes: #99
Signed-off-by: Kai Krakow <[email protected]>
  • Loading branch information
3 people committed Mar 28, 2021
1 parent 5be5996 commit 1bcec4b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 3 deletions.
78 changes: 76 additions & 2 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -970,14 +974,37 @@ 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)
{
struct xpadneo_devdata *xdata = hid_get_drvdata(hdev);
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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion hid-xpadneo/src/xpadneo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define XPADNEO_H_FILE

#include <linux/hid.h>
#include <linux/timer.h>
#include <linux/version.h>

#include "hid-ids.h"
Expand Down Expand Up @@ -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 */
Expand All @@ -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 {
Expand Down

0 comments on commit 1bcec4b

Please sign in to comment.