543 lines
19 KiB
Diff
543 lines
19 KiB
Diff
|
diff -rupN hid.orig/hid-ids.h hid/hid-ids.h
|
||
|
--- linux/drivers/hid.orig/hid-ids.h 2022-11-10 18:46:50.091977625 -0800
|
||
|
+++ linux/drivers/hid/hid-ids.h 2022-11-10 18:51:51.442399828 -0800
|
||
|
@@ -1175,6 +1175,7 @@
|
||
|
|
||
|
#define USB_VENDOR_ID_VALVE 0x28de
|
||
|
#define USB_DEVICE_ID_STEAM_CONTROLLER 0x1102
|
||
|
+#define USB_DEVICE_ID_STEAM_DECK_CONTROLLER 0x1205
|
||
|
#define USB_DEVICE_ID_STEAM_CONTROLLER_WIRELESS 0x1142
|
||
|
|
||
|
#define USB_VENDOR_ID_STEELSERIES 0x1038
|
||
|
diff -rupN hid.orig/hid-steam.c hid/hid-steam.c
|
||
|
--- linux/drivers/hid.orig/hid-steam.c 2022-11-10 18:46:50.095977727 -0800
|
||
|
+++ linux/drivers/hid/hid-steam.c 2022-11-10 18:50:19.152673800 -0800
|
||
|
@@ -42,6 +42,9 @@
|
||
|
#include <linux/rcupdate.h>
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/power_supply.h>
|
||
|
+#include <linux/kthread.h>
|
||
|
+#include <linux/sched.h>
|
||
|
+#include <linux/delay.h>
|
||
|
#include "hid-ids.h"
|
||
|
|
||
|
MODULE_LICENSE("GPL");
|
||
|
@@ -54,6 +57,7 @@ static LIST_HEAD(steam_devices);
|
||
|
|
||
|
#define STEAM_QUIRK_WIRELESS BIT(0)
|
||
|
|
||
|
+int lizard_reset_fn (void *data);
|
||
|
/* Touch pads are 40 mm in diameter and 65535 units */
|
||
|
#define STEAM_PAD_RESOLUTION 1638
|
||
|
/* Trigger runs are about 5 mm and 256 units */
|
||
|
@@ -82,9 +86,10 @@ static LIST_HEAD(steam_devices);
|
||
|
#define STEAM_CMD_GET_REGISTER_DEFAULT 0x8c
|
||
|
#define STEAM_CMD_SET_MODE 0x8d
|
||
|
#define STEAM_CMD_DEFAULT_MOUSE 0x8e
|
||
|
-#define STEAM_CMD_FORCEFEEDBAK 0x8f
|
||
|
+#define STEAM_CMD_TOUCHPAD_HAPTIC 0x8f
|
||
|
#define STEAM_CMD_REQUEST_COMM_STATUS 0xb4
|
||
|
#define STEAM_CMD_GET_SERIAL 0xae
|
||
|
+#define STEAM_CMD_RUMBLE 0xeb
|
||
|
|
||
|
/* Some useful register ids */
|
||
|
#define STEAM_REG_LPAD_MODE 0x07
|
||
|
@@ -97,6 +102,7 @@ static LIST_HEAD(steam_devices);
|
||
|
#define STEAM_EV_INPUT_DATA 0x01
|
||
|
#define STEAM_EV_CONNECT 0x03
|
||
|
#define STEAM_EV_BATTERY 0x04
|
||
|
+#define STEAM_DECK_EV_INPUT_DATA 0x09
|
||
|
|
||
|
/* Values for GYRO_MODE (bitmask) */
|
||
|
#define STEAM_GYRO_MODE_OFF 0x0000
|
||
|
@@ -118,12 +124,18 @@ struct steam_device {
|
||
|
struct input_dev __rcu *input;
|
||
|
unsigned long quirks;
|
||
|
struct work_struct work_connect;
|
||
|
+ struct work_struct work_effect;
|
||
|
bool connected;
|
||
|
char serial_no[STEAM_SERIAL_LEN + 1];
|
||
|
struct power_supply_desc battery_desc;
|
||
|
struct power_supply __rcu *battery;
|
||
|
u8 battery_charge;
|
||
|
u16 voltage;
|
||
|
+ bool steamdeck;
|
||
|
+ bool device_open;
|
||
|
+ struct task_struct *lizard_reset;
|
||
|
+ uint32_t rumble_weak;
|
||
|
+ uint32_t rumble_strong;
|
||
|
};
|
||
|
|
||
|
static int steam_recv_report(struct steam_device *steam,
|
||
|
@@ -165,6 +177,7 @@ static int steam_send_report(struct stea
|
||
|
u8 *cmd, int size)
|
||
|
{
|
||
|
struct hid_report *r;
|
||
|
+ u32 len;
|
||
|
u8 *buf;
|
||
|
unsigned int retries = 50;
|
||
|
int ret;
|
||
|
@@ -175,13 +188,15 @@ static int steam_send_report(struct stea
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
- if (hid_report_len(r) < 64)
|
||
|
+ len = hid_report_len(r);
|
||
|
+ if (len < 64)
|
||
|
return -EINVAL;
|
||
|
|
||
|
buf = hid_alloc_report_buf(r, GFP_KERNEL);
|
||
|
if (!buf)
|
||
|
return -ENOMEM;
|
||
|
|
||
|
+ memset(buf, 0, len);
|
||
|
/* The report ID is always 0 */
|
||
|
memcpy(buf + 1, cmd, size);
|
||
|
|
||
|
@@ -193,7 +208,7 @@ static int steam_send_report(struct stea
|
||
|
*/
|
||
|
do {
|
||
|
ret = hid_hw_raw_request(steam->hdev, 0,
|
||
|
- buf, size + 1,
|
||
|
+ buf, len,
|
||
|
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
|
||
|
if (ret != -EPIPE)
|
||
|
break;
|
||
|
@@ -273,6 +288,10 @@ static inline int steam_request_conn_sta
|
||
|
static void steam_set_lizard_mode(struct steam_device *steam, bool enable)
|
||
|
{
|
||
|
if (enable) {
|
||
|
+ if (steam->lizard_reset) {
|
||
|
+ kthread_stop(steam->lizard_reset);
|
||
|
+ steam->lizard_reset = NULL;
|
||
|
+ }
|
||
|
/* enable esc, enter, cursors */
|
||
|
steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS);
|
||
|
/* enable mouse */
|
||
|
@@ -287,17 +306,39 @@ static void steam_set_lizard_mode(struct
|
||
|
STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */
|
||
|
STEAM_REG_RPAD_MARGIN, 0x00, /* disable margin */
|
||
|
0);
|
||
|
+
|
||
|
+ if (steam->lizard_reset)
|
||
|
+ return;
|
||
|
+ steam->lizard_reset = kthread_create(lizard_reset_fn, (void*)steam, "lizard_reset");
|
||
|
+ if (IS_ERR(steam->lizard_reset)) {
|
||
|
+ steam->lizard_reset = NULL;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ wake_up_process(steam->lizard_reset);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+int lizard_reset_fn (void *data) {
|
||
|
+ struct steam_device *steam = (struct steam_device*)data;
|
||
|
+ while (steam->device_open) {
|
||
|
+ mutex_lock(&steam->mutex);
|
||
|
+ steam_set_lizard_mode(steam, false);
|
||
|
+ mutex_unlock(&steam->mutex);
|
||
|
+ msleep(1000);
|
||
|
}
|
||
|
+ return 0;
|
||
|
}
|
||
|
|
||
|
static int steam_input_open(struct input_dev *dev)
|
||
|
{
|
||
|
struct steam_device *steam = input_get_drvdata(dev);
|
||
|
-
|
||
|
+ steam->device_open = 1;
|
||
|
mutex_lock(&steam->mutex);
|
||
|
if (!steam->client_opened && lizard_mode)
|
||
|
steam_set_lizard_mode(steam, false);
|
||
|
mutex_unlock(&steam->mutex);
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -305,6 +346,7 @@ static void steam_input_close(struct inp
|
||
|
{
|
||
|
struct steam_device *steam = input_get_drvdata(dev);
|
||
|
|
||
|
+ steam->device_open = 0;
|
||
|
mutex_lock(&steam->mutex);
|
||
|
if (!steam->client_opened && lizard_mode)
|
||
|
steam_set_lizard_mode(steam, true);
|
||
|
@@ -390,6 +432,62 @@ static int steam_battery_register(struct
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int steam_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
|
||
|
+{
|
||
|
+ struct steam_device *steam = input_get_drvdata(dev);
|
||
|
+ unsigned long flags;
|
||
|
+ u32 strong, weak;
|
||
|
+
|
||
|
+ if (effect->u.rumble.strong_magnitude == 0 && effect->u.rumble.weak_magnitude == 0)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ /* Steam uses a factor of 1.33 to the values. */
|
||
|
+ strong = (effect->u.rumble.strong_magnitude * 100ul) / 75;
|
||
|
+ weak = (effect->u.rumble.weak_magnitude * 100ul) / 75;
|
||
|
+
|
||
|
+ /* Clamp values to 16 bit */
|
||
|
+ if (strong > 0xffff)
|
||
|
+ strong = 0xffff;
|
||
|
+
|
||
|
+ if (weak > 0xffff)
|
||
|
+ weak = 0xffff;
|
||
|
+
|
||
|
+ spin_lock_irqsave(&steam->lock, flags);
|
||
|
+ steam->rumble_strong = strong;
|
||
|
+ steam->rumble_weak = weak;
|
||
|
+ spin_unlock_irqrestore(&steam->lock, flags);
|
||
|
+
|
||
|
+ schedule_work(&steam->work_effect);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+/**
|
||
|
+ * Prepares the command buffer for the rumble command.
|
||
|
+ * It is reverse-engineered from captured traces when using Steam's
|
||
|
+ * controller support.
|
||
|
+ */
|
||
|
+static void prepare_effect_buffer(u8 *buf,uint16_t strong, uint16_t weak)
|
||
|
+{
|
||
|
+ buf[0] = STEAM_CMD_RUMBLE;
|
||
|
+ buf[1] = 9;
|
||
|
+ buf[2] = 1;
|
||
|
+ buf[3] = 0x40;
|
||
|
+ buf[4] = 0x1f;
|
||
|
+ buf[5] = strong & 0xff;
|
||
|
+ buf[6] = strong >> 8;
|
||
|
+ buf[7] = weak & 0xff;
|
||
|
+ buf[8] = weak >> 8;
|
||
|
+}
|
||
|
+
|
||
|
+static void steam_play_effect_cb(struct work_struct *work)
|
||
|
+{
|
||
|
+ struct steam_device *steam = container_of(work, struct steam_device, work_effect);
|
||
|
+ u8 cmd_buf[9];
|
||
|
+ prepare_effect_buffer(cmd_buf, steam->rumble_strong, steam->rumble_weak);
|
||
|
+ mutex_lock(&steam->mutex);
|
||
|
+ steam_send_report(steam, cmd_buf, sizeof(cmd_buf));
|
||
|
+ mutex_unlock(&steam->mutex);
|
||
|
+}
|
||
|
+
|
||
|
static int steam_input_register(struct steam_device *steam)
|
||
|
{
|
||
|
struct hid_device *hdev = steam->hdev;
|
||
|
@@ -423,48 +521,107 @@ static int steam_input_register(struct s
|
||
|
input->id.product = hdev->product;
|
||
|
input->id.version = hdev->version;
|
||
|
|
||
|
- input_set_capability(input, EV_KEY, BTN_TR2);
|
||
|
- input_set_capability(input, EV_KEY, BTN_TL2);
|
||
|
- input_set_capability(input, EV_KEY, BTN_TR);
|
||
|
- input_set_capability(input, EV_KEY, BTN_TL);
|
||
|
- input_set_capability(input, EV_KEY, BTN_Y);
|
||
|
- input_set_capability(input, EV_KEY, BTN_B);
|
||
|
- input_set_capability(input, EV_KEY, BTN_X);
|
||
|
- input_set_capability(input, EV_KEY, BTN_A);
|
||
|
- input_set_capability(input, EV_KEY, BTN_DPAD_UP);
|
||
|
- input_set_capability(input, EV_KEY, BTN_DPAD_RIGHT);
|
||
|
- input_set_capability(input, EV_KEY, BTN_DPAD_LEFT);
|
||
|
- input_set_capability(input, EV_KEY, BTN_DPAD_DOWN);
|
||
|
- input_set_capability(input, EV_KEY, BTN_SELECT);
|
||
|
- input_set_capability(input, EV_KEY, BTN_MODE);
|
||
|
- input_set_capability(input, EV_KEY, BTN_START);
|
||
|
- input_set_capability(input, EV_KEY, BTN_GEAR_DOWN);
|
||
|
- input_set_capability(input, EV_KEY, BTN_GEAR_UP);
|
||
|
- input_set_capability(input, EV_KEY, BTN_THUMBR);
|
||
|
- input_set_capability(input, EV_KEY, BTN_THUMBL);
|
||
|
- input_set_capability(input, EV_KEY, BTN_THUMB);
|
||
|
- input_set_capability(input, EV_KEY, BTN_THUMB2);
|
||
|
-
|
||
|
- input_set_abs_params(input, ABS_HAT2Y, 0, 255, 0, 0);
|
||
|
- input_set_abs_params(input, ABS_HAT2X, 0, 255, 0, 0);
|
||
|
- input_set_abs_params(input, ABS_X, -32767, 32767, 0, 0);
|
||
|
- input_set_abs_params(input, ABS_Y, -32767, 32767, 0, 0);
|
||
|
- input_set_abs_params(input, ABS_RX, -32767, 32767,
|
||
|
- STEAM_PAD_FUZZ, 0);
|
||
|
- input_set_abs_params(input, ABS_RY, -32767, 32767,
|
||
|
- STEAM_PAD_FUZZ, 0);
|
||
|
- input_set_abs_params(input, ABS_HAT0X, -32767, 32767,
|
||
|
- STEAM_PAD_FUZZ, 0);
|
||
|
- input_set_abs_params(input, ABS_HAT0Y, -32767, 32767,
|
||
|
- STEAM_PAD_FUZZ, 0);
|
||
|
- input_abs_set_res(input, ABS_X, STEAM_JOYSTICK_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_Y, STEAM_JOYSTICK_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_RX, STEAM_PAD_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_RY, STEAM_PAD_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_HAT0X, STEAM_PAD_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_HAT0Y, STEAM_PAD_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_HAT2Y, STEAM_TRIGGER_RESOLUTION);
|
||
|
- input_abs_set_res(input, ABS_HAT2X, STEAM_TRIGGER_RESOLUTION);
|
||
|
+ if (!steam->steamdeck) {
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TR2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TL2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TR);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TL);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_Y);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_B);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_X);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_A);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_UP);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_RIGHT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_LEFT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_DOWN);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_SELECT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_MODE);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_START);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_GEAR_DOWN);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_GEAR_UP);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMBR);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMBL);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMB);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMB2);
|
||
|
+
|
||
|
+ input_set_abs_params(input, ABS_HAT2Y, 0, 255, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT2X, 0, 255, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_X, -32767, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_Y, -32767, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_RX, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_RY, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT0X, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT0Y, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_abs_set_res(input, ABS_X, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_Y, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_RX, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_RY, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT0X, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT0Y, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT2Y, STEAM_TRIGGER_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT2X, STEAM_TRIGGER_RESOLUTION);
|
||
|
+ } else {
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TR2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TL2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TR);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_TL);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_Y);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_B);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_X);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_A);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_UP);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_RIGHT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_LEFT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_DPAD_DOWN);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_SELECT);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_MODE);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_START);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_GEAR_DOWN);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_GEAR_UP);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMBR);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMBL);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMB);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_THUMB2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_BASE);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_BASE2);
|
||
|
+ input_set_capability(input, EV_KEY, BTN_MISC);
|
||
|
+
|
||
|
+ input_set_abs_params(input, ABS_Z, 0, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_RZ, 0, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_X, -32767, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_Y, -32767, 32767, 0, 0);
|
||
|
+ input_set_abs_params(input, ABS_RX, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_RY, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT0X, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT0Y, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT1X, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_set_abs_params(input, ABS_HAT1Y, -32767, 32767,
|
||
|
+ STEAM_PAD_FUZZ, 0);
|
||
|
+ input_abs_set_res(input, ABS_HAT0X, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT0Y, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT1X, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_HAT1Y, STEAM_PAD_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_X, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_Y, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_RX, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_RY, STEAM_JOYSTICK_RESOLUTION);
|
||
|
+
|
||
|
+ input_abs_set_res(input, ABS_Z, STEAM_TRIGGER_RESOLUTION);
|
||
|
+ input_abs_set_res(input, ABS_RZ, STEAM_TRIGGER_RESOLUTION);
|
||
|
+
|
||
|
+
|
||
|
+ input_set_capability(input, EV_FF, FF_RUMBLE);
|
||
|
+ input_ff_create_memless(input, NULL, steam_play_effect);
|
||
|
+ }
|
||
|
|
||
|
ret = input_register_device(input);
|
||
|
if (ret)
|
||
|
@@ -670,6 +827,14 @@ static int steam_client_ll_raw_request(s
|
||
|
{
|
||
|
struct steam_device *steam = hdev->driver_data;
|
||
|
|
||
|
+ /*if (buf[1] != STEAM_CMD_CLEAR_MAPPINGS ) {
|
||
|
+ pr_info("Steam cmd=%x count=%x\n", buf[1], count);
|
||
|
+ for (size_t i = 0; i < count; i++) {
|
||
|
+ pr_cont("%x,",buf[i]);
|
||
|
+ if ((i+1) % 8 == 0)
|
||
|
+ pr_cont("\n");
|
||
|
+ }
|
||
|
+ }*/
|
||
|
return hid_hw_raw_request(steam->hdev, reportnum, buf, count,
|
||
|
report_type, reqtype);
|
||
|
}
|
||
|
@@ -743,12 +908,19 @@ static int steam_probe(struct hid_device
|
||
|
ret = -ENOMEM;
|
||
|
goto steam_alloc_fail;
|
||
|
}
|
||
|
+
|
||
|
+ if (id->product == USB_DEVICE_ID_STEAM_DECK_CONTROLLER) {
|
||
|
+ hid_info(hdev, "Steam Deck Controller connected\n");
|
||
|
+ steam->steamdeck = 1;
|
||
|
+ }
|
||
|
+
|
||
|
steam->hdev = hdev;
|
||
|
hid_set_drvdata(hdev, steam);
|
||
|
spin_lock_init(&steam->lock);
|
||
|
mutex_init(&steam->mutex);
|
||
|
steam->quirks = id->driver_data;
|
||
|
INIT_WORK(&steam->work_connect, steam_work_connect_cb);
|
||
|
+ INIT_WORK(&steam->work_effect, steam_play_effect_cb);
|
||
|
INIT_LIST_HEAD(&steam->list);
|
||
|
|
||
|
steam->client_hdev = steam_create_client_hid(hdev);
|
||
|
@@ -805,6 +977,7 @@ hid_hw_start_fail:
|
||
|
hid_destroy_device(steam->client_hdev);
|
||
|
client_hdev_fail:
|
||
|
cancel_work_sync(&steam->work_connect);
|
||
|
+ cancel_work_sync(&steam->work_effect);
|
||
|
steam_alloc_fail:
|
||
|
hid_err(hdev, "%s: failed with error %d\n",
|
||
|
__func__, ret);
|
||
|
@@ -823,6 +996,7 @@ static void steam_remove(struct hid_devi
|
||
|
hid_destroy_device(steam->client_hdev);
|
||
|
steam->client_opened = false;
|
||
|
cancel_work_sync(&steam->work_connect);
|
||
|
+ cancel_work_sync(&steam->work_effect);
|
||
|
if (steam->quirks & STEAM_QUIRK_WIRELESS) {
|
||
|
hid_info(hdev, "Steam wireless receiver disconnected");
|
||
|
}
|
||
|
@@ -993,6 +1167,78 @@ static void steam_do_input_event(struct
|
||
|
input_sync(input);
|
||
|
}
|
||
|
|
||
|
+static void steam_deck_do_input_event(struct steam_device *steam,
|
||
|
+ struct input_dev *input, u8 *data)
|
||
|
+{
|
||
|
+ /* 24 bits of buttons */
|
||
|
+ u8 b8, b9, b10, b11, b12, b13, b14;
|
||
|
+
|
||
|
+ b8 = data[8];
|
||
|
+ b9 = data[9];
|
||
|
+ b10 = data[10];
|
||
|
+ b11 = data[11];
|
||
|
+ b12 = data[12];
|
||
|
+ b13 = data[13];
|
||
|
+ b14 = data[14];
|
||
|
+
|
||
|
+ /* Left analog joystick */
|
||
|
+ input_report_abs(input, ABS_X, steam_le16(data + 48));
|
||
|
+ input_report_abs(input, ABS_Y, -steam_le16(data + 50));
|
||
|
+
|
||
|
+ /* Right analog joystick */
|
||
|
+ input_report_abs(input, ABS_RX, steam_le16(data + 52));
|
||
|
+ input_report_abs(input, ABS_RY, -steam_le16(data + 54));
|
||
|
+
|
||
|
+ /* Left touchpad */
|
||
|
+ input_report_abs(input, ABS_HAT0X, steam_le16(data + 16));
|
||
|
+ input_report_abs(input, ABS_HAT0Y, -steam_le16(data + 18));
|
||
|
+
|
||
|
+ /* Right touchpad */
|
||
|
+ input_report_abs(input, ABS_HAT1X, steam_le16(data + 20));
|
||
|
+ input_report_abs(input, ABS_HAT1Y, -steam_le16(data + 22));
|
||
|
+
|
||
|
+ /* Trigger */
|
||
|
+ input_report_abs(input, ABS_Z, steam_le16(data + 44));
|
||
|
+ input_report_abs(input, ABS_RZ, steam_le16(data + 46));
|
||
|
+
|
||
|
+ input_event(input, EV_KEY, BTN_TR2, !!(b8 & BIT(0)));
|
||
|
+ input_event(input, EV_KEY, BTN_TL2, !!(b8 & BIT(1)));
|
||
|
+ input_event(input, EV_KEY, BTN_TR, !!(b8 & BIT(2)));
|
||
|
+ input_event(input, EV_KEY, BTN_TL, !!(b8 & BIT(3)));
|
||
|
+ input_event(input, EV_KEY, BTN_SELECT, !!(b9 & BIT(4)));
|
||
|
+ input_event(input, EV_KEY, BTN_MODE, !!(b9 & BIT(5)));
|
||
|
+ input_event(input, EV_KEY, BTN_START, !!(b9 & BIT(6)));
|
||
|
+ input_event(input, EV_KEY, BTN_THUMBR, !!(b11 & BIT(2)));
|
||
|
+ input_event(input, EV_KEY, BTN_THUMBL, !!(b10 & BIT(6)));
|
||
|
+ input_event(input, EV_KEY, BTN_THUMB, !!(b10 & BIT(1)));
|
||
|
+ input_event(input, EV_KEY, BTN_THUMB2, !!(b10 & BIT(2)));
|
||
|
+
|
||
|
+ input_event(input, EV_KEY, BTN_SELECT, !!(b9 & BIT(4)));
|
||
|
+ input_event(input, EV_KEY, BTN_MODE, !!(b9 & BIT(5)));
|
||
|
+ input_event(input, EV_KEY, BTN_START, !!(b9 & BIT(6)));
|
||
|
+ input_event(input, EV_KEY, BTN_Y, !!(b8 & BIT(4)));
|
||
|
+ input_event(input, EV_KEY, BTN_B, !!(b8 & BIT(5)));
|
||
|
+ input_event(input, EV_KEY, BTN_X, !!(b8 & BIT(6)));
|
||
|
+ input_event(input, EV_KEY, BTN_A, !!(b8 & BIT(7)));
|
||
|
+ input_event(input, EV_KEY, BTN_DPAD_UP, !!(b9 & BIT(0)));
|
||
|
+ input_event(input, EV_KEY, BTN_DPAD_RIGHT, !!(b9 & BIT(1)));
|
||
|
+ input_event(input, EV_KEY, BTN_DPAD_LEFT, !!(b9 & BIT(2)));
|
||
|
+ input_event(input, EV_KEY, BTN_DPAD_DOWN, !!(b9 & BIT(3)));
|
||
|
+
|
||
|
+ /* Back button lower left L5 */
|
||
|
+ input_event(input, EV_KEY, BTN_GEAR_DOWN, !!(b9 & BIT(7)));
|
||
|
+ /* Back button lower right R5 */
|
||
|
+ input_event(input, EV_KEY, BTN_GEAR_UP, !!(b10 & BIT(0)));
|
||
|
+ /* Back button upper left L4 */
|
||
|
+ input_event(input, EV_KEY, BTN_BASE, !!(b13 & BIT(1)));
|
||
|
+ /* Back button upper right R4 */
|
||
|
+ input_event(input, EV_KEY, BTN_BASE2, !!(b13 & BIT(2)));
|
||
|
+
|
||
|
+ /* Menu botton right (3 dots) */
|
||
|
+ input_event(input, EV_KEY, BTN_MISC, !!(b14 & BIT(2)));
|
||
|
+ input_sync(input);
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* The size for this message payload is 11.
|
||
|
* The known values are:
|
||
|
@@ -1054,10 +1300,21 @@ static int steam_raw_event(struct hid_de
|
||
|
* 0x04: battery status (11 bytes)
|
||
|
*/
|
||
|
|
||
|
- if (size != 64 || data[0] != 1 || data[1] != 0)
|
||
|
+ if (size != 64 || data[0] != 1 || data[1] != 0) {
|
||
|
+ hid_info(hdev, "Can_t use it\n");
|
||
|
return 0;
|
||
|
+ }
|
||
|
|
||
|
switch (data[2]) {
|
||
|
+ case STEAM_DECK_EV_INPUT_DATA:
|
||
|
+ if (steam->client_opened)
|
||
|
+ return 0;
|
||
|
+ rcu_read_lock();
|
||
|
+ input = rcu_dereference(steam->input);
|
||
|
+ if (likely(input))
|
||
|
+ steam_deck_do_input_event(steam, input, data);
|
||
|
+ rcu_read_unlock();
|
||
|
+ break;
|
||
|
case STEAM_EV_INPUT_DATA:
|
||
|
if (steam->client_opened)
|
||
|
return 0;
|
||
|
@@ -1136,6 +1393,10 @@ static const struct hid_device_id steam_
|
||
|
HID_USB_DEVICE(USB_VENDOR_ID_VALVE,
|
||
|
USB_DEVICE_ID_STEAM_CONTROLLER)
|
||
|
},
|
||
|
+ { /* Wired Steam Deck Controller */
|
||
|
+ HID_USB_DEVICE(USB_VENDOR_ID_VALVE,
|
||
|
+ USB_DEVICE_ID_STEAM_DECK_CONTROLLER)
|
||
|
+ },
|
||
|
{ /* Wireless Steam Controller */
|
||
|
HID_USB_DEVICE(USB_VENDOR_ID_VALVE,
|
||
|
USB_DEVICE_ID_STEAM_CONTROLLER_WIRELESS),
|