Skip to content

Commit ffbb921

Browse files
kakraJacob Essexatar-axis
committed
xpadneo, mouse: Implement mouse support
Co-authored-by: Jacob Essex <git@jacobessex.com> Co-authored-by: Florian Dollinger <dollinger.florian@gmx.de> Closes: atar-axis#99 Closes: atar-axis#105 Closes: atar-axis#160 Closes: atar-axis#511 Fixes: atar-axis#333 See-also: atar-axis#419 See-also: atar-axis#435 Signed-off-by: Kai Krakow <kai@kaishome.de>
1 parent 6a43a76 commit ffbb921

File tree

8 files changed

+295
-17
lines changed

8 files changed

+295
-17
lines changed

docs/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ PID 0x0B22 while the other models identify with PID 0x0B13. This has some known
9191
* Supports customization through profiles (work in progress)
9292
* Optional high-precision mode for Wine/Proton users (disables dead zones so games don't apply an additional one)
9393
* Share button support on supported controllers
94+
* Works as a mouse if you're are in couch-mode (press <key>Guide</key>+<key>Select</key>)
9495

9596

9697
## Unavailable Features
@@ -239,6 +240,24 @@ or Y while holding down the Xbox logo button. However, the following caveats app
239240
parameter `disable_shift_mode`).
240241

241242

243+
### Mouse Profile Support
244+
245+
The driver can switch to emulating a mouse (and limited keyboard) on all supported controllers. Press
246+
<key>Guide</key>+<key>Select</key> to switch to mouse mode or back to controller mode:
247+
248+
- Left stick moves the mouse pointer
249+
- Right stick can be used as a scrolling wheel/ball
250+
- Triggers for left and right mouse button
251+
- Shoulder buttons for back and forward button
252+
- D-pad for cursor movement
253+
- Menu to show on-screen keyboard (FIXME possible? KEY_KEYBOARD)
254+
- A for <key>Enter</key>
255+
- B for <key>Escape</key>
256+
257+
**Important:** The mouse profile won't work if you disabled the shift-mode of the Xbox logo button (module parameter
258+
`disable_shift_mode`).
259+
260+
242261
## Getting Started
243262

244263
### Distribution Packages

hid-xpadneo/src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ hid-xpadneo-y += xpadneo.o
99
$(obj)/xpadneo.c: $(src)/hid-xpadneo.c
1010
cp $< $@
1111

12-
hid-xpadneo-y += xpadneo/core.o xpadneo/consumer.o xpadneo/keyboard.o
12+
hid-xpadneo-y += xpadneo/core.o xpadneo/consumer.o xpadneo/keyboard.o xpadneo/mouse.o

hid-xpadneo/src/hid-xpadneo.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -731,20 +731,6 @@ static const __u8 *xpadneo_report_fixup(struct hid_device *hdev, __u8 *rdesc, un
731731
return rdesc;
732732
}
733733

734-
static void xpadneo_toggle_mouse(struct xpadneo_devdata *xdata)
735-
{
736-
if (xdata->mouse_mode) {
737-
xdata->mouse_mode = false;
738-
hid_info(xdata->hdev, "mouse mode disabled\n");
739-
} else {
740-
xdata->mouse_mode = true;
741-
hid_info(xdata->hdev, "mouse mode enabled\n");
742-
}
743-
744-
/* Indicate that a request was made */
745-
xdata->profile_switched = true;
746-
}
747-
748734
static void xpadneo_switch_profile(struct xpadneo_devdata *xdata, const u8 profile,
749735
const bool emulated)
750736
{
@@ -851,6 +837,9 @@ static int xpadneo_raw_event(struct hid_device *hdev, struct hid_report *report,
851837
}
852838
}
853839

840+
if (xpadneo_mouse_raw_event(xdata, report, data, reportsize))
841+
return -1;
842+
854843
return 0;
855844
}
856845

@@ -883,6 +872,7 @@ static int xpadneo_input_configured(struct hid_device *hdev, struct hid_input *h
883872
return 0;
884873
default:
885874
hid_warn(hdev, "unhandled input application 0x%x\n", hi->application);
875+
return 0;
886876
}
887877

888878
if (param_disable_deadzones) {
@@ -932,6 +922,9 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
932922
struct input_dev *gamepad = xdata->gamepad;
933923
struct input_dev *keyboard = xdata->keyboard;
934924

925+
if (xpadneo_mouse_event(xdata, usage, value))
926+
goto stop_processing;
927+
935928
if ((usage->type == EV_KEY) && (usage->code == BTN_PADDLES(0))) {
936929
if (gamepad && xdata->profile == 0) {
937930
/* report the paddles individually */
@@ -1234,6 +1227,10 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id
12341227
if (ret)
12351228
return ret;
12361229

1230+
ret = xpadneo_init_mouse(xdata);
1231+
if (ret)
1232+
return ret;
1233+
12371234
ret = xpadneo_init_hw(hdev);
12381235
if (ret) {
12391236
hid_err(hdev, "hw init failed: %d\n", ret);
@@ -1245,6 +1242,9 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id
12451242
if (ret)
12461243
hid_err(hdev, "could not initialize ff, continuing anyway\n");
12471244

1245+
timer_setup(&xdata->mouse_timer, xpadneo_mouse_report, 0);
1246+
mod_timer(&xdata->mouse_timer, jiffies);
1247+
12481248
hid_info(hdev, "%s connected\n", xdata->battery.name);
12491249

12501250
return 0;
@@ -1280,6 +1280,7 @@ static void xpadneo_remove(struct hid_device *hdev)
12801280
hdev->product = xdata->original_product;
12811281
}
12821282

1283+
del_timer_sync(&xdata->mouse_timer);
12831284
cancel_delayed_work_sync(&xdata->ff_worker);
12841285

12851286
kfree(xdata->battery.name);

hid-xpadneo/src/xpadneo.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define XPADNEO_H_FILE
1313

1414
#include <linux/hid.h>
15+
#include <linux/timer.h>
1516
#include <linux/version.h>
1617

1718
#include "hid-ids.h"
@@ -143,8 +144,8 @@ struct xpadneo_devdata {
143144

144145
/* logical device interfaces */
145146
struct hid_device *hdev;
146-
struct input_dev *consumer, *gamepad, *keyboard;
147-
bool consumer_sync, gamepad_sync, keyboard_sync;
147+
struct input_dev *consumer, *gamepad, *keyboard, *mouse;
148+
bool consumer_sync, gamepad_sync, keyboard_sync, mouse_sync;
148149
short int missing_reported;
149150

150151
/* revert fixups on removal */
@@ -161,6 +162,14 @@ struct xpadneo_devdata {
161162

162163
/* mouse mode */
163164
bool mouse_mode;
165+
struct timer_list mouse_timer;
166+
struct {
167+
s32 rel_x, rel_y, wheel_x, wheel_y;
168+
s32 rel_x_err, rel_y_err, wheel_x_err, wheel_y_err;
169+
struct {
170+
bool left, right;
171+
} analog_button;
172+
} mouse_state;
164173

165174
/* trigger scale */
166175
struct {
@@ -198,8 +207,13 @@ struct xpadneo_devdata {
198207

199208
extern int xpadneo_init_consumer(struct xpadneo_devdata *);
200209
extern int xpadneo_init_keyboard(struct xpadneo_devdata *);
210+
extern int xpadneo_init_mouse(struct xpadneo_devdata *);
201211
extern int xpadneo_init_synthetic(struct xpadneo_devdata *, char *, struct input_dev **);
212+
extern int xpadneo_mouse_event(struct xpadneo_devdata *, struct hid_usage *, __s32);
213+
extern int xpadneo_mouse_raw_event(struct xpadneo_devdata *, struct hid_report *, u8 *, int);
202214
extern void xpadneo_report(struct hid_device *, struct hid_report *);
203215
extern void xpadneo_core_missing(struct xpadneo_devdata *, u32);
216+
extern void xpadneo_mouse_report(struct timer_list *);
217+
extern void xpadneo_toggle_mouse(struct xpadneo_devdata *);
204218

205219
#endif

hid-xpadneo/src/xpadneo/consumer.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ extern int xpadneo_init_consumer(struct xpadneo_devdata *xdata)
1818
return ret;
1919
}
2020

21+
/* enable consumer events for mouse mode */
22+
input_set_capability(xdata->consumer, EV_KEY, KEY_ONSCREEN_KEYBOARD);
23+
2124
if (synth) {
2225
ret = input_register_device(xdata->consumer);
2326
if (ret) {

hid-xpadneo/src/xpadneo/core.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ extern void xpadneo_report(struct hid_device *hdev, struct hid_report *report)
5454
xdata->keyboard_sync = false;
5555
input_sync(xdata->keyboard);
5656
}
57+
58+
if (xdata->mouse && xdata->mouse_sync) {
59+
xdata->mouse_sync = false;
60+
input_sync(xdata->mouse);
61+
}
5762
}
5863

5964
extern void xpadneo_core_missing(struct xpadneo_devdata *xdata, u32 flag)
@@ -63,6 +68,9 @@ extern void xpadneo_core_missing(struct xpadneo_devdata *xdata, u32 flag)
6368
if ((xdata->missing_reported & flag) == 0) {
6469
xdata->missing_reported |= flag;
6570
switch (flag) {
71+
case XPADNEO_MISSING_CONSUMER:
72+
hid_err(hdev, "consumer control not detected\n");
73+
break;
6674
case XPADNEO_MISSING_GAMEPAD:
6775
hid_err(hdev, "gamepad not detected\n");
6876
break;

hid-xpadneo/src/xpadneo/keyboard.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ extern int xpadneo_init_keyboard(struct xpadneo_devdata *xdata)
2121
/* enable key events for keyboard */
2222
input_set_capability(xdata->keyboard, EV_KEY, BTN_SHARE);
2323

24+
/* enable key events for mouse mode */
25+
input_set_capability(xdata->keyboard, EV_KEY, KEY_ESC);
26+
input_set_capability(xdata->keyboard, EV_KEY, KEY_ENTER);
27+
input_set_capability(xdata->keyboard, EV_KEY, KEY_UP);
28+
input_set_capability(xdata->keyboard, EV_KEY, KEY_LEFT);
29+
input_set_capability(xdata->keyboard, EV_KEY, KEY_RIGHT);
30+
input_set_capability(xdata->keyboard, EV_KEY, KEY_DOWN);
31+
2432
if (synth) {
2533
ret = input_register_device(xdata->keyboard);
2634
if (ret) {

0 commit comments

Comments
 (0)