Skip to content

Commit

Permalink
xpadneo, core: Handle sync events in xpadneo
Browse files Browse the repository at this point in the history
To properly sync our multiple sub-devices, we need to synchronize the
input frame in xpadneo instead of the generic HID handler, otherwise
we may see input late or duplicated.

See-also: atar-axis#460
See-also: atar-axis#282
Signed-off-by: Kai Krakow <[email protected]>
  • Loading branch information
kakra committed Mar 4, 2024
1 parent d593fa3 commit 5ab9bcf
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
10 changes: 9 additions & 1 deletion hid-xpadneo/src/hid-xpadneo.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
input_report_key(gamepad, BTN_PADDLES(1), value & 2 ? 1 : 0);
input_report_key(gamepad, BTN_PADDLES(2), value & 4 ? 1 : 0);
input_report_key(gamepad, BTN_PADDLES(3), value & 8 ? 1 : 0);
xdata->gamepad_sync = true;
}
goto stop_processing;
} else if (usage->type == EV_ABS) {
Expand All @@ -928,6 +929,7 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
/* Linux Gamepad Specification */
if (param_gamepad_compliance) {
input_report_abs(gamepad, usage->code, value - 32768);
xdata->gamepad_sync = true;
goto stop_processing;
}
break;
Expand Down Expand Up @@ -967,6 +969,7 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
if (!keyboard)
goto keyboard_missing;
input_report_key(keyboard, BTN_SHARE, value);
xdata->keyboard_sync = true;
goto stop_processing;
} else if (xdata->xbox_button_down && (usage->type == EV_KEY)) {
if (!(xdata->quirks & XPADNEO_QUIRK_USE_HW_PROFILES)) {
Expand Down Expand Up @@ -996,13 +999,16 @@ static int xpadneo_event(struct hid_device *hdev, struct hid_field *field,
}

/* Let hid-core handle the event */
xdata->gamepad_sync = true;
return 0;

combine_z_axes:
if (++xdata->count_abs_z_rz == 2) {
xdata->count_abs_z_rz = 0;
if (param_enable_rolling_axis)
if (param_enable_rolling_axis) {
input_report_abs(gamepad, ABS_MISC, xdata->last_abs_rz - xdata->last_abs_z);
xdata->gamepad_sync = true;
}
}
return 0;

Expand Down Expand Up @@ -1114,6 +1120,7 @@ static int xpadneo_probe(struct hid_device *hdev, const struct hid_device_id *id

xdata->hdev = hdev;
hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
hid_set_drvdata(hdev, xdata);

if (hdev->version == 0x00000903)
Expand Down Expand Up @@ -1281,6 +1288,7 @@ static struct hid_driver xpadneo_driver = {
.input_configured = xpadneo_input_configured,
.probe = xpadneo_probe,
.remove = xpadneo_remove,
.report = xpadneo_report,
.report_fixup = xpadneo_report_fixup,
.raw_event = xpadneo_raw_event,
.event = xpadneo_event,
Expand Down
2 changes: 2 additions & 0 deletions hid-xpadneo/src/xpadneo.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct xpadneo_devdata {
/* logical device interfaces */
struct hid_device *hdev;
struct input_dev *consumer, *gamepad, *keyboard;
bool consumer_sync, gamepad_sync, keyboard_sync;
short int missing_reported;

/* revert fixups on removal */
Expand Down Expand Up @@ -193,5 +194,6 @@ struct xpadneo_devdata {
extern int xpadneo_init_consumer(struct xpadneo_devdata *);
extern int xpadneo_init_keyboard(struct xpadneo_devdata *);
extern int xpadneo_init_synthetic(struct xpadneo_devdata *, char *, struct input_dev **);
extern void xpadneo_report(struct hid_device *, struct hid_report *);

#endif
20 changes: 20 additions & 0 deletions hid-xpadneo/src/xpadneo/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,23 @@ extern int xpadneo_init_synthetic(struct xpadneo_devdata *xdata, char *suffix,
*devp = input_dev;
return 0;
}

extern void xpadneo_report(struct hid_device *hdev, struct hid_report *report)
{
struct xpadneo_devdata *xdata = hid_get_drvdata(hdev);

if (xdata->consumer && xdata->consumer_sync) {
xdata->consumer_sync = false;
input_sync(xdata->consumer);
}

if (xdata->gamepad && xdata->gamepad_sync) {
xdata->gamepad_sync = false;
input_sync(xdata->gamepad);
}

if (xdata->keyboard && xdata->keyboard_sync) {
xdata->keyboard_sync = false;
input_sync(xdata->keyboard);
}
}

0 comments on commit 5ab9bcf

Please sign in to comment.