mirror of
https://github.com/libretro/Lakka-LibreELEC.git
synced 2025-03-01 06:51:22 +00:00
82 lines
2.8 KiB
Diff
82 lines
2.8 KiB
Diff
From 97a1b64cc4e00f29e4ff3d4301f8e9ce6d060b65 Mon Sep 17 00:00:00 2001
|
|
From: "Daniel J. Ogorchock" <djogorchock@gmail.com>
|
|
Date: Sat, 5 Sep 2020 01:14:14 -0500
|
|
Subject: [PATCH] HID: nintendo: improve rumble performance and stability
|
|
|
|
This patch alters the method that the rumble data is sent to the
|
|
controller. Rather than using the enable rumble subcommand for this
|
|
purpose, the driver now employs the RUMBLE_ONLY output report. This has
|
|
the advantage of not needing to receive a subcommand reply (to the major
|
|
benefit of reducing IMU latency) and also seems to make the rumble
|
|
vibrations more continuous. Perhaps most importantly it reduces
|
|
disconnects during times of heavy rumble.
|
|
|
|
Signed-off-by: Daniel J. Ogorchock <djogorchock@gmail.com>
|
|
---
|
|
drivers/hid/hid-nintendo.c | 38 +++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 37 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
|
|
index 9bbab3bbeaf1..ccd3011bbfe5 100644
|
|
--- a/drivers/hid/hid-nintendo.c
|
|
+++ b/drivers/hid/hid-nintendo.c
|
|
@@ -348,6 +348,12 @@ enum joycon_msg_type {
|
|
JOYCON_MSG_TYPE_SUBCMD,
|
|
};
|
|
|
|
+struct joycon_rumble_output {
|
|
+ u8 output_id;
|
|
+ u8 packet_num;
|
|
+ u8 rumble_data[8];
|
|
+} __packed;
|
|
+
|
|
struct joycon_subcmd_request {
|
|
u8 output_id; /* must be 0x01 for subcommand, 0x10 for rumble only */
|
|
u8 packet_num; /* incremented every send */
|
|
@@ -1324,6 +1330,36 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
|
|
joycon_parse_imu_report(ctlr, rep);
|
|
}
|
|
|
|
+static int joycon_send_rumble_data(struct joycon_ctlr *ctlr)
|
|
+{
|
|
+ int ret;
|
|
+ unsigned long flags;
|
|
+ struct joycon_rumble_output rumble_output = { 0 };
|
|
+
|
|
+ spin_lock_irqsave(&ctlr->lock, flags);
|
|
+ /*
|
|
+ * If the controller has been removed, just return ENODEV so the LED
|
|
+ * subsystem doesn't print invalid errors on removal.
|
|
+ */
|
|
+ if (ctlr->ctlr_state == JOYCON_CTLR_STATE_REMOVED) {
|
|
+ spin_unlock_irqrestore(&ctlr->lock, flags);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ memcpy(rumble_output.rumble_data,
|
|
+ ctlr->rumble_data[ctlr->rumble_queue_tail],
|
|
+ JC_RUMBLE_DATA_SIZE);
|
|
+ spin_unlock_irqrestore(&ctlr->lock, flags);
|
|
+
|
|
+ rumble_output.output_id = JC_OUTPUT_RUMBLE_ONLY;
|
|
+ rumble_output.packet_num = ctlr->subcmd_num;
|
|
+ if (++ctlr->subcmd_num > 0xF)
|
|
+ ctlr->subcmd_num = 0;
|
|
+
|
|
+ ret = __joycon_hid_send(ctlr->hdev, (u8 *)&rumble_output,
|
|
+ sizeof(rumble_output));
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static void joycon_rumble_worker(struct work_struct *work)
|
|
{
|
|
struct joycon_ctlr *ctlr = container_of(work, struct joycon_ctlr,
|
|
@@ -1334,7 +1370,7 @@ static void joycon_rumble_worker(struct work_struct *work)
|
|
|
|
while (again) {
|
|
mutex_lock(&ctlr->output_mutex);
|
|
- ret = joycon_enable_rumble(ctlr, true);
|
|
+ ret = joycon_send_rumble_data(ctlr);
|
|
mutex_unlock(&ctlr->output_mutex);
|
|
|
|
/* -ENODEV means the controller was just unplugged */
|