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

Add patch for trigger rumble on Xbox controllers #64

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
165 changes: 165 additions & 0 deletions 6.9/misc/0001-trigger-rumble.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
From 648d4f032006095ded8b047c533f594f009b1180 Mon Sep 17 00:00:00 2001
From: Daniel Bomar <dbdaniel42@gmail.com>
Date: Thu, 20 Jun 2024 15:26:54 +0200
Subject: [PATCH] input: Implement an API for trigger rumble motors

This patchset extends the force feedback API to allow userspace to control
the force feedback motors underneath the triggers in some gamepads.

Patches 3 and 4 of this patchset implement this API in the xpad and
hid-microsoft drivers for the Xbox One controller over USB and bluetooth
respectively.

---
drivers/hid/hid-microsoft.c | 14 ++++++++++++--
drivers/input/ff-memless.c | 8 +++++++-
drivers/input/joystick/xpad.c | 8 ++++++--
include/uapi/linux/input.h | 4 ++++
4 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index 9345e2bfd56e..2020e897be4c 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -32,6 +32,8 @@ struct ms_data {
unsigned long quirks;
struct hid_device *hdev;
struct work_struct ff_worker;
+ __u8 trigger_left;
+ __u8 trigger_right;
__u8 strong;
__u8 weak;
void *output_report_dmabuf;
@@ -40,9 +42,13 @@ struct ms_data {
#define XB1S_FF_REPORT 3
#define ENABLE_WEAK BIT(0)
#define ENABLE_STRONG BIT(1)
+#define ENABLE_RIGHT BIT(2)
+#define ENABLE_LEFT BIT(3)

enum {
- MAGNITUDE_STRONG = 2,
+ MAGNITUDE_LEFT,
+ MAGNITUDE_RIGHT,
+ MAGNITUDE_STRONG,
MAGNITUDE_WEAK,
MAGNITUDE_NUM
};
@@ -288,7 +294,7 @@ static void ms_ff_worker(struct work_struct *work)
memset(r, 0, sizeof(*r));

r->report_id = XB1S_FF_REPORT;
- r->enable = ENABLE_WEAK | ENABLE_STRONG;
+ r->enable = ENABLE_WEAK | ENABLE_STRONG | ENABLE_RIGHT | ENABLE_LEFT;
/*
* Specifying maximum duration and maximum loop count should
* cover maximum duration of a single effect, which is 65536
@@ -296,6 +302,8 @@ static void ms_ff_worker(struct work_struct *work)
*/
r->duration_10ms = U8_MAX;
r->loop_count = U8_MAX;
+ r->magnitude[MAGNITUDE_LEFT] = ms->trigger_left;
+ r->magnitude[MAGNITUDE_RIGHT] = ms->trigger_right;
r->magnitude[MAGNITUDE_STRONG] = ms->strong; /* left actuator */
r->magnitude[MAGNITUDE_WEAK] = ms->weak; /* right actuator */

@@ -316,6 +324,8 @@ static int ms_play_effect(struct input_dev *dev, void *data,
/*
* Magnitude is 0..100 so scale the 16-bit input here
*/
+ ms->trigger_left = ((u32) effect->u.rumble.trigger_left * 100) / U16_MAX;
+ ms->trigger_right = ((u32) effect->u.rumble.trigger_right * 100) / U16_MAX;
ms->strong = ((u32) effect->u.rumble.strong_magnitude * 100) / U16_MAX;
ms->weak = ((u32) effect->u.rumble.weak_magnitude * 100) / U16_MAX;

diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index c321cdabd214..6b7f916e2b14 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -242,7 +242,7 @@ static void ml_combine_effects(struct ff_effect *effect,
int gain)
{
struct ff_effect *new = state->effect;
- unsigned int strong, weak, i;
+ unsigned int strong, weak, trigger_left, trigger_right, i;
int x, y;
s16 level;

@@ -268,6 +268,8 @@ static void ml_combine_effects(struct ff_effect *effect,
case FF_RUMBLE:
strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff;
weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff;
+ trigger_left = (u32)new->u.rumble.trigger_left * gain / 0xffff;
+ trigger_right = (u32)new->u.rumble.trigger_right * gain / 0xffff;

if (effect->u.rumble.strong_magnitude + strong)
effect->direction = ml_calculate_direction(
@@ -286,6 +288,10 @@ static void ml_combine_effects(struct ff_effect *effect,
0xffffU);
effect->u.rumble.weak_magnitude =
min(weak + effect->u.rumble.weak_magnitude, 0xffffU);
+ effect->u.rumble.trigger_left =
+ min(trigger_left + effect->u.rumble.trigger_left, 0xffffU);
+ effect->u.rumble.trigger_right =
+ min(trigger_right + effect->u.rumble.trigger_right, 0xffffU);
break;

case FF_PERIODIC:
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 6fadaddb2b90..4cba9b42f61d 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1483,6 +1483,8 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX];
__u16 strong;
__u16 weak;
+ __u16 trigger_left;
+ __u16 trigger_right;
int retval;
unsigned long flags;

@@ -1491,6 +1493,8 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect

strong = effect->u.rumble.strong_magnitude;
weak = effect->u.rumble.weak_magnitude;
+ trigger_left = effect->u.rumble.trigger_left;
+ trigger_right = effect->u.rumble.trigger_right;

spin_lock_irqsave(&xpad->odata_lock, flags);

@@ -1543,8 +1547,8 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
packet->data[3] = GIP_PL_LEN(9);
packet->data[4] = 0x00;
packet->data[5] = GIP_MOTOR_ALL;
- packet->data[6] = 0x00; /* left trigger */
- packet->data[7] = 0x00; /* right trigger */
+ packet->data[6] = trigger_left / 512; /* left trigger */
+ packet->data[7] = trigger_right / 512; /* right trigger */
packet->data[8] = strong / 512; /* left actuator */
packet->data[9] = weak / 512; /* right actuator */
packet->data[10] = 0xFF; /* on period */
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index 2557eb7b0561..9f35b97720e3 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -419,6 +419,8 @@ struct ff_periodic_effect {
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
* @strong_magnitude: magnitude of the heavy motor
* @weak_magnitude: magnitude of the light one
+ * @trigger_left: magnitude of the motor behind the left trigger
+ * @trigger_right: magnitude of the motor behind the right trigger
*
* Some rumble pads have two motors of different weight. Strong_magnitude
* represents the magnitude of the vibration generated by the heavy one.
@@ -426,6 +428,8 @@ struct ff_periodic_effect {
struct ff_rumble_effect {
__u16 strong_magnitude;
__u16 weak_magnitude;
+ __u16 trigger_left;
+ __u16 trigger_right;
};

/**
--
2.45.2