Skip to content

Commit 3347e16

Browse files
Max MaiselJiri Kosina
authored andcommitted
HID: hid-steam: Add Deck IMU support
The Deck's controller features an accelerometer and gyroscope which send their measurement values by default in the main HID input report. Expose both sensors to userspace through a separate evdev node as it is done by the hid-nintendo and hid-playstation drivers. Signed-off-by: Max Maisel <[email protected]> Reviewed-by: Vicki Pfau <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 3e78a6c commit 3347e16

File tree

1 file changed

+147
-8
lines changed

1 file changed

+147
-8
lines changed

drivers/hid/hid-steam.c

Lines changed: 147 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ static LIST_HEAD(steam_devices);
6666
#define STEAM_DECK_TRIGGER_RESOLUTION 5461
6767
/* Joystick runs are about 5 mm and 32768 units */
6868
#define STEAM_DECK_JOYSTICK_RESOLUTION 6553
69+
/* Accelerometer has 16 bit resolution and a range of +/- 2g */
70+
#define STEAM_DECK_ACCEL_RES_PER_G 16384
71+
#define STEAM_DECK_ACCEL_RANGE 32768
72+
#define STEAM_DECK_ACCEL_FUZZ 32
73+
/* Gyroscope has 16 bit resolution and a range of +/- 2000 dps */
74+
#define STEAM_DECK_GYRO_RES_PER_DPS 16
75+
#define STEAM_DECK_GYRO_RANGE 32768
76+
#define STEAM_DECK_GYRO_FUZZ 1
6977

7078
#define STEAM_PAD_FUZZ 256
7179

@@ -288,6 +296,7 @@ struct steam_device {
288296
struct mutex report_mutex;
289297
unsigned long client_opened;
290298
struct input_dev __rcu *input;
299+
struct input_dev __rcu *sensors;
291300
unsigned long quirks;
292301
struct work_struct work_connect;
293302
bool connected;
@@ -302,6 +311,7 @@ struct steam_device {
302311
struct work_struct rumble_work;
303312
u16 rumble_left;
304313
u16 rumble_right;
314+
unsigned int sensor_timestamp_us;
305315
};
306316

307317
static int steam_recv_report(struct steam_device *steam,
@@ -825,6 +835,74 @@ static int steam_input_register(struct steam_device *steam)
825835
return ret;
826836
}
827837

838+
static int steam_sensors_register(struct steam_device *steam)
839+
{
840+
struct hid_device *hdev = steam->hdev;
841+
struct input_dev *sensors;
842+
int ret;
843+
844+
if (!(steam->quirks & STEAM_QUIRK_DECK))
845+
return 0;
846+
847+
rcu_read_lock();
848+
sensors = rcu_dereference(steam->sensors);
849+
rcu_read_unlock();
850+
if (sensors) {
851+
dbg_hid("%s: already connected\n", __func__);
852+
return 0;
853+
}
854+
855+
sensors = input_allocate_device();
856+
if (!sensors)
857+
return -ENOMEM;
858+
859+
input_set_drvdata(sensors, steam);
860+
sensors->dev.parent = &hdev->dev;
861+
862+
sensors->name = "Steam Deck Motion Sensors";
863+
sensors->phys = hdev->phys;
864+
sensors->uniq = steam->serial_no;
865+
sensors->id.bustype = hdev->bus;
866+
sensors->id.vendor = hdev->vendor;
867+
sensors->id.product = hdev->product;
868+
sensors->id.version = hdev->version;
869+
870+
__set_bit(INPUT_PROP_ACCELEROMETER, sensors->propbit);
871+
__set_bit(EV_MSC, sensors->evbit);
872+
__set_bit(MSC_TIMESTAMP, sensors->mscbit);
873+
874+
input_set_abs_params(sensors, ABS_X, -STEAM_DECK_ACCEL_RANGE,
875+
STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0);
876+
input_set_abs_params(sensors, ABS_Y, -STEAM_DECK_ACCEL_RANGE,
877+
STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0);
878+
input_set_abs_params(sensors, ABS_Z, -STEAM_DECK_ACCEL_RANGE,
879+
STEAM_DECK_ACCEL_RANGE, STEAM_DECK_ACCEL_FUZZ, 0);
880+
input_abs_set_res(sensors, ABS_X, STEAM_DECK_ACCEL_RES_PER_G);
881+
input_abs_set_res(sensors, ABS_Y, STEAM_DECK_ACCEL_RES_PER_G);
882+
input_abs_set_res(sensors, ABS_Z, STEAM_DECK_ACCEL_RES_PER_G);
883+
884+
input_set_abs_params(sensors, ABS_RX, -STEAM_DECK_GYRO_RANGE,
885+
STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0);
886+
input_set_abs_params(sensors, ABS_RY, -STEAM_DECK_GYRO_RANGE,
887+
STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0);
888+
input_set_abs_params(sensors, ABS_RZ, -STEAM_DECK_GYRO_RANGE,
889+
STEAM_DECK_GYRO_RANGE, STEAM_DECK_GYRO_FUZZ, 0);
890+
input_abs_set_res(sensors, ABS_RX, STEAM_DECK_GYRO_RES_PER_DPS);
891+
input_abs_set_res(sensors, ABS_RY, STEAM_DECK_GYRO_RES_PER_DPS);
892+
input_abs_set_res(sensors, ABS_RZ, STEAM_DECK_GYRO_RES_PER_DPS);
893+
894+
ret = input_register_device(sensors);
895+
if (ret)
896+
goto sensors_register_fail;
897+
898+
rcu_assign_pointer(steam->sensors, sensors);
899+
return 0;
900+
901+
sensors_register_fail:
902+
input_free_device(sensors);
903+
return ret;
904+
}
905+
828906
static void steam_input_unregister(struct steam_device *steam)
829907
{
830908
struct input_dev *input;
@@ -838,6 +916,24 @@ static void steam_input_unregister(struct steam_device *steam)
838916
input_unregister_device(input);
839917
}
840918

919+
static void steam_sensors_unregister(struct steam_device *steam)
920+
{
921+
struct input_dev *sensors;
922+
923+
if (!(steam->quirks & STEAM_QUIRK_DECK))
924+
return;
925+
926+
rcu_read_lock();
927+
sensors = rcu_dereference(steam->sensors);
928+
rcu_read_unlock();
929+
930+
if (!sensors)
931+
return;
932+
RCU_INIT_POINTER(steam->sensors, NULL);
933+
synchronize_rcu();
934+
input_unregister_device(sensors);
935+
}
936+
841937
static void steam_battery_unregister(struct steam_device *steam)
842938
{
843939
struct power_supply *battery;
@@ -890,18 +986,28 @@ static int steam_register(struct steam_device *steam)
890986
spin_lock_irqsave(&steam->lock, flags);
891987
client_opened = steam->client_opened;
892988
spin_unlock_irqrestore(&steam->lock, flags);
989+
893990
if (!client_opened) {
894991
steam_set_lizard_mode(steam, lizard_mode);
895992
ret = steam_input_register(steam);
896-
} else
897-
ret = 0;
993+
if (ret != 0)
994+
goto steam_register_input_fail;
995+
ret = steam_sensors_register(steam);
996+
if (ret != 0)
997+
goto steam_register_sensors_fail;
998+
}
999+
return 0;
8981000

1001+
steam_register_sensors_fail:
1002+
steam_input_unregister(steam);
1003+
steam_register_input_fail:
8991004
return ret;
9001005
}
9011006

9021007
static void steam_unregister(struct steam_device *steam)
9031008
{
9041009
steam_battery_unregister(steam);
1010+
steam_sensors_unregister(steam);
9051011
steam_input_unregister(steam);
9061012
if (steam->serial_no[0]) {
9071013
hid_info(steam->hdev, "Steam Controller '%s' disconnected",
@@ -1010,6 +1116,7 @@ static int steam_client_ll_open(struct hid_device *hdev)
10101116
steam->client_opened++;
10111117
spin_unlock_irqrestore(&steam->lock, flags);
10121118

1119+
steam_sensors_unregister(steam);
10131120
steam_input_unregister(steam);
10141121

10151122
return 0;
@@ -1030,6 +1137,7 @@ static void steam_client_ll_close(struct hid_device *hdev)
10301137
if (connected) {
10311138
steam_set_lizard_mode(steam, lizard_mode);
10321139
steam_input_register(steam);
1140+
steam_sensors_register(steam);
10331141
}
10341142
}
10351143

@@ -1121,6 +1229,7 @@ static int steam_probe(struct hid_device *hdev,
11211229
INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb);
11221230
INIT_LIST_HEAD(&steam->list);
11231231
INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb);
1232+
steam->sensor_timestamp_us = 0;
11241233

11251234
/*
11261235
* With the real steam controller interface, do not connect hidraw.
@@ -1380,12 +1489,12 @@ static void steam_do_input_event(struct steam_device *steam,
13801489
* 18-19 | s16 | ABS_HAT0Y | left-pad Y value
13811490
* 20-21 | s16 | ABS_HAT1X | right-pad X value
13821491
* 22-23 | s16 | ABS_HAT1Y | right-pad Y value
1383-
* 24-25 | s16 | -- | accelerometer X value
1384-
* 26-27 | s16 | -- | accelerometer Y value
1385-
* 28-29 | s16 | -- | accelerometer Z value
1386-
* 30-31 | s16 | -- | gyro X value
1387-
* 32-33 | s16 | -- | gyro Y value
1388-
* 34-35 | s16 | -- | gyro Z value
1492+
* 24-25 | s16 | IMU ABS_X | accelerometer X value
1493+
* 26-27 | s16 | IMU ABS_Z | accelerometer Y value
1494+
* 28-29 | s16 | IMU ABS_Y | accelerometer Z value
1495+
* 30-31 | s16 | IMU ABS_RX | gyro X value
1496+
* 32-33 | s16 | IMU ABS_RZ | gyro Y value
1497+
* 34-35 | s16 | IMU ABS_RY | gyro Z value
13891498
* 36-37 | s16 | -- | quaternion W value
13901499
* 38-39 | s16 | -- | quaternion X value
13911500
* 40-41 | s16 | -- | quaternion Y value
@@ -1546,6 +1655,32 @@ static void steam_do_deck_input_event(struct steam_device *steam,
15461655
input_sync(input);
15471656
}
15481657

1658+
static void steam_do_deck_sensors_event(struct steam_device *steam,
1659+
struct input_dev *sensors, u8 *data)
1660+
{
1661+
/*
1662+
* The deck input report is received every 4 ms on average,
1663+
* with a jitter of +/- 4 ms even though the USB descriptor claims
1664+
* that it uses 1 kHz.
1665+
* Since the HID report does not include a sensor timestamp,
1666+
* use a fixed increment here.
1667+
*/
1668+
steam->sensor_timestamp_us += 4000;
1669+
1670+
if (!steam->gamepad_mode)
1671+
return;
1672+
1673+
input_event(sensors, EV_MSC, MSC_TIMESTAMP, steam->sensor_timestamp_us);
1674+
input_report_abs(sensors, ABS_X, steam_le16(data + 24));
1675+
input_report_abs(sensors, ABS_Z, -steam_le16(data + 26));
1676+
input_report_abs(sensors, ABS_Y, steam_le16(data + 28));
1677+
input_report_abs(sensors, ABS_RX, steam_le16(data + 30));
1678+
input_report_abs(sensors, ABS_RZ, -steam_le16(data + 32));
1679+
input_report_abs(sensors, ABS_RY, steam_le16(data + 34));
1680+
1681+
input_sync(sensors);
1682+
}
1683+
15491684
/*
15501685
* The size for this message payload is 11.
15511686
* The known values are:
@@ -1583,6 +1718,7 @@ static int steam_raw_event(struct hid_device *hdev,
15831718
{
15841719
struct steam_device *steam = hid_get_drvdata(hdev);
15851720
struct input_dev *input;
1721+
struct input_dev *sensors;
15861722
struct power_supply *battery;
15871723

15881724
if (!steam)
@@ -1628,6 +1764,9 @@ static int steam_raw_event(struct hid_device *hdev,
16281764
input = rcu_dereference(steam->input);
16291765
if (likely(input))
16301766
steam_do_deck_input_event(steam, input, data);
1767+
sensors = rcu_dereference(steam->sensors);
1768+
if (likely(sensors))
1769+
steam_do_deck_sensors_event(steam, sensors, data);
16311770
rcu_read_unlock();
16321771
break;
16331772
case ID_CONTROLLER_WIRELESS:

0 commit comments

Comments
 (0)