Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement mouse mode #282

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ PID 0x0B22 while the other models identify with PID 0x0B13. This has some known
* Supports customization through profiles (work in progress)
* Optional high-precision mode for Wine/Proton users (disables dead zones so games don't apply an additional one)
* Share button support on supported controllers
* Works as a mouse if you're are in couch-mode (press <key>Guide</key>+<key>Select</key>)


## Unavailable Features
Expand Down Expand Up @@ -222,6 +223,24 @@ or Y while holding down the Xbox logo button. However, the following caveats app
parameter `disable_shift_mode`).


### Mouse Profile Support

The driver can switch to emulating a mouse (and limited keyboard) on all supported controllers. Press
<key>Guide</key>+<key>Select</key> to switch to mouse mode or back to controller mode:

- Left stick moves the mouse pointer
- Right stick can be used as a scrolling wheel/ball
- Triggers for left and right mouse button
- Shoulder buttons for back and forward button
- D-pad for cursor movement
- Menu to show on-screen keyboard (FIXME possible? KEY_KEYBOARD)
- A for <key>Enter</key>
- B for <key>Escape</key>

**Important:** The mouse profile won't work if you disabled the shift-mode of the Xbox logo button (module parameter
`disable_shift_mode`).


## Getting Started

### Distribution Packages
Expand Down
2 changes: 1 addition & 1 deletion hid-xpadneo/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ hid-xpadneo-y += xpadneo.o
$(obj)/xpadneo.c: $(src)/hid-xpadneo.c
cp $< $@

hid-xpadneo-y += xpadneo/core.o xpadneo/consumer.o xpadneo/keyboard.o
hid-xpadneo-y += xpadneo/core.o xpadneo/consumer.o xpadneo/keyboard.o xpadneo/mouse.o
29 changes: 15 additions & 14 deletions hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -719,20 +719,6 @@ static const __u8 *xpadneo_report_fixup(struct hid_device *hdev, __u8 *rdesc, un
return rdesc;
}

static void xpadneo_toggle_mouse(struct xpadneo_devdata *xdata)
{
if (xdata->mouse_mode) {
xdata->mouse_mode = false;
hid_info(xdata->hdev, "mouse mode disabled\n");
} else {
xdata->mouse_mode = true;
hid_info(xdata->hdev, "mouse mode enabled\n");
}

/* Indicate that a request was made */
xdata->profile_switched = true;
}

static void xpadneo_switch_profile(struct xpadneo_devdata *xdata, const u8 profile,
const bool emulated)
{
Expand Down Expand Up @@ -839,6 +825,9 @@ static int xpadneo_raw_event(struct hid_device *hdev, struct hid_report *report,
}
}

if (xpadneo_mouse_raw_event(xdata, report, data, reportsize))
return -1;

return 0;
}

Expand Down Expand Up @@ -871,6 +860,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;
}

if (param_disable_deadzones) {
Expand Down Expand Up @@ -920,6 +910,9 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
struct input_dev *gamepad = xdata->gamepad;
struct input_dev *keyboard = xdata->keyboard;

if (xpadneo_mouse_event(xdata, usage, value))
goto stop_processing;

if ((usage->type == EV_KEY) && (usage->code == BTN_PADDLES(0))) {
if (gamepad && xdata->profile == 0) {
/* report the paddles individually */
Expand Down Expand Up @@ -1206,6 +1199,10 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id
if (ret)
return ret;

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 @@ -1217,6 +1214,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_report, 0);
mod_timer(&xdata->mouse_timer, jiffies);

hid_info(hdev, "%s connected\n", xdata->battery.name);

return 0;
Expand Down Expand Up @@ -1252,6 +1252,7 @@ static void xpadneo_remove(struct hid_device *hdev)
hdev->product = xdata->original_product;
}

del_timer_sync(&xdata->mouse_timer);
cancel_delayed_work_sync(&xdata->ff_worker);

kfree(xdata->battery.name);
Expand Down
18 changes: 16 additions & 2 deletions 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 @@ -138,8 +139,8 @@ struct xpadneo_devdata {

/* logical device interfaces */
struct hid_device *hdev;
struct input_dev *consumer, *gamepad, *keyboard;
bool consumer_sync, gamepad_sync, keyboard_sync;
struct input_dev *consumer, *gamepad, *keyboard, *mouse;
bool consumer_sync, gamepad_sync, keyboard_sync, mouse_sync;
short int missing_reported;

/* revert fixups on removal */
Expand All @@ -156,6 +157,14 @@ struct xpadneo_devdata {

/* mouse mode */
bool mouse_mode;
struct timer_list mouse_timer;
struct {
s32 rel_x, rel_y, wheel_x, wheel_y;
s32 rel_x_err, rel_y_err, wheel_x_err, wheel_y_err;
struct {
bool left, right;
} analog_button;
} mouse_state;

/* trigger scale */
struct {
Expand Down Expand Up @@ -193,8 +202,13 @@ struct xpadneo_devdata {

extern int xpadneo_init_consumer(struct xpadneo_devdata *);
extern int xpadneo_init_keyboard(struct xpadneo_devdata *);
extern int xpadneo_init_mouse(struct xpadneo_devdata *);
extern int xpadneo_init_synthetic(struct xpadneo_devdata *, char *, struct input_dev **);
extern int xpadneo_mouse_event(struct xpadneo_devdata *, struct hid_usage *, __s32);
extern int xpadneo_mouse_raw_event(struct xpadneo_devdata *, struct hid_report *, u8 *, int);
extern void xpadneo_report(struct hid_device *, struct hid_report *);
extern void xpadneo_core_missing(struct xpadneo_devdata *, u32);
extern void xpadneo_mouse_report(struct timer_list *);
extern void xpadneo_toggle_mouse(struct xpadneo_devdata *);

#endif
3 changes: 3 additions & 0 deletions hid-xpadneo/src/xpadneo/consumer.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ extern int xpadneo_init_consumer(struct xpadneo_devdata *xdata)
return ret;
}

/* enable consumer events for mouse mode */
input_set_capability(xdata->consumer, EV_KEY, KEY_ONSCREEN_KEYBOARD);

if (synth) {
ret = input_register_device(xdata->consumer);
if (ret) {
Expand Down
8 changes: 8 additions & 0 deletions hid-xpadneo/src/xpadneo/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ extern void xpadneo_report(struct hid_device *hdev, struct hid_report *report)
xdata->keyboard_sync = false;
input_sync(xdata->keyboard);
}

if (xdata->mouse && xdata->mouse_sync) {
xdata->mouse_sync = false;
input_sync(xdata->mouse);
}
}

extern void xpadneo_core_missing(struct xpadneo_devdata *xdata, u32 flag)
Expand All @@ -63,6 +68,9 @@ extern void xpadneo_core_missing(struct xpadneo_devdata *xdata, u32 flag)
if ((xdata->missing_reported & flag) == 0) {
xdata->missing_reported |= flag;
switch (flag) {
case XPADNEO_MISSING_CONSUMER:
hid_err(hdev, "consumer control not detected\n");
break;
case XPADNEO_MISSING_GAMEPAD:
hid_err(hdev, "gamepad not detected\n");
break;
Expand Down
8 changes: 8 additions & 0 deletions hid-xpadneo/src/xpadneo/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ extern int xpadneo_init_keyboard(struct xpadneo_devdata *xdata)
/* enable key events for keyboard */
input_set_capability(xdata->keyboard, EV_KEY, BTN_SHARE);

/* enable key events for mouse mode */
input_set_capability(xdata->keyboard, EV_KEY, KEY_ESC);
input_set_capability(xdata->keyboard, EV_KEY, KEY_ENTER);
input_set_capability(xdata->keyboard, EV_KEY, KEY_UP);
input_set_capability(xdata->keyboard, EV_KEY, KEY_LEFT);
input_set_capability(xdata->keyboard, EV_KEY, KEY_RIGHT);
input_set_capability(xdata->keyboard, EV_KEY, KEY_DOWN);

if (synth) {
ret = input_register_device(xdata->keyboard);
if (ret) {
Expand Down
Loading