Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
55b04252
Commit
55b04252
authored
May 14, 2024
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-6.10/steam' into for-linus
- support for Deck IMU in hid-steam (Max Maisel)
parents
47846941
3347e165
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
147 additions
and
8 deletions
+147
-8
drivers/hid/hid-steam.c
drivers/hid/hid-steam.c
+147
-8
No files found.
drivers/hid/hid-steam.c
View file @
55b04252
...
...
@@ -66,6 +66,14 @@ static LIST_HEAD(steam_devices);
#define STEAM_DECK_TRIGGER_RESOLUTION 5461
/* Joystick runs are about 5 mm and 32768 units */
#define STEAM_DECK_JOYSTICK_RESOLUTION 6553
/* Accelerometer has 16 bit resolution and a range of +/- 2g */
#define STEAM_DECK_ACCEL_RES_PER_G 16384
#define STEAM_DECK_ACCEL_RANGE 32768
#define STEAM_DECK_ACCEL_FUZZ 32
/* Gyroscope has 16 bit resolution and a range of +/- 2000 dps */
#define STEAM_DECK_GYRO_RES_PER_DPS 16
#define STEAM_DECK_GYRO_RANGE 32768
#define STEAM_DECK_GYRO_FUZZ 1
#define STEAM_PAD_FUZZ 256
...
...
@@ -288,6 +296,7 @@ struct steam_device {
struct
mutex
report_mutex
;
unsigned
long
client_opened
;
struct
input_dev
__rcu
*
input
;
struct
input_dev
__rcu
*
sensors
;
unsigned
long
quirks
;
struct
work_struct
work_connect
;
bool
connected
;
...
...
@@ -302,6 +311,7 @@ struct steam_device {
struct
work_struct
rumble_work
;
u16
rumble_left
;
u16
rumble_right
;
unsigned
int
sensor_timestamp_us
;
};
static
int
steam_recv_report
(
struct
steam_device
*
steam
,
...
...
@@ -825,6 +835,74 @@ static int steam_input_register(struct steam_device *steam)
return
ret
;
}
static
int
steam_sensors_register
(
struct
steam_device
*
steam
)
{
struct
hid_device
*
hdev
=
steam
->
hdev
;
struct
input_dev
*
sensors
;
int
ret
;
if
(
!
(
steam
->
quirks
&
STEAM_QUIRK_DECK
))
return
0
;
rcu_read_lock
();
sensors
=
rcu_dereference
(
steam
->
sensors
);
rcu_read_unlock
();
if
(
sensors
)
{
dbg_hid
(
"%s: already connected
\n
"
,
__func__
);
return
0
;
}
sensors
=
input_allocate_device
();
if
(
!
sensors
)
return
-
ENOMEM
;
input_set_drvdata
(
sensors
,
steam
);
sensors
->
dev
.
parent
=
&
hdev
->
dev
;
sensors
->
name
=
"Steam Deck Motion Sensors"
;
sensors
->
phys
=
hdev
->
phys
;
sensors
->
uniq
=
steam
->
serial_no
;
sensors
->
id
.
bustype
=
hdev
->
bus
;
sensors
->
id
.
vendor
=
hdev
->
vendor
;
sensors
->
id
.
product
=
hdev
->
product
;
sensors
->
id
.
version
=
hdev
->
version
;
__set_bit
(
INPUT_PROP_ACCELEROMETER
,
sensors
->
propbit
);
__set_bit
(
EV_MSC
,
sensors
->
evbit
);
__set_bit
(
MSC_TIMESTAMP
,
sensors
->
mscbit
);
input_set_abs_params
(
sensors
,
ABS_X
,
-
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_FUZZ
,
0
);
input_set_abs_params
(
sensors
,
ABS_Y
,
-
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_FUZZ
,
0
);
input_set_abs_params
(
sensors
,
ABS_Z
,
-
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_RANGE
,
STEAM_DECK_ACCEL_FUZZ
,
0
);
input_abs_set_res
(
sensors
,
ABS_X
,
STEAM_DECK_ACCEL_RES_PER_G
);
input_abs_set_res
(
sensors
,
ABS_Y
,
STEAM_DECK_ACCEL_RES_PER_G
);
input_abs_set_res
(
sensors
,
ABS_Z
,
STEAM_DECK_ACCEL_RES_PER_G
);
input_set_abs_params
(
sensors
,
ABS_RX
,
-
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_FUZZ
,
0
);
input_set_abs_params
(
sensors
,
ABS_RY
,
-
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_FUZZ
,
0
);
input_set_abs_params
(
sensors
,
ABS_RZ
,
-
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_RANGE
,
STEAM_DECK_GYRO_FUZZ
,
0
);
input_abs_set_res
(
sensors
,
ABS_RX
,
STEAM_DECK_GYRO_RES_PER_DPS
);
input_abs_set_res
(
sensors
,
ABS_RY
,
STEAM_DECK_GYRO_RES_PER_DPS
);
input_abs_set_res
(
sensors
,
ABS_RZ
,
STEAM_DECK_GYRO_RES_PER_DPS
);
ret
=
input_register_device
(
sensors
);
if
(
ret
)
goto
sensors_register_fail
;
rcu_assign_pointer
(
steam
->
sensors
,
sensors
);
return
0
;
sensors_register_fail:
input_free_device
(
sensors
);
return
ret
;
}
static
void
steam_input_unregister
(
struct
steam_device
*
steam
)
{
struct
input_dev
*
input
;
...
...
@@ -838,6 +916,24 @@ static void steam_input_unregister(struct steam_device *steam)
input_unregister_device
(
input
);
}
static
void
steam_sensors_unregister
(
struct
steam_device
*
steam
)
{
struct
input_dev
*
sensors
;
if
(
!
(
steam
->
quirks
&
STEAM_QUIRK_DECK
))
return
;
rcu_read_lock
();
sensors
=
rcu_dereference
(
steam
->
sensors
);
rcu_read_unlock
();
if
(
!
sensors
)
return
;
RCU_INIT_POINTER
(
steam
->
sensors
,
NULL
);
synchronize_rcu
();
input_unregister_device
(
sensors
);
}
static
void
steam_battery_unregister
(
struct
steam_device
*
steam
)
{
struct
power_supply
*
battery
;
...
...
@@ -890,18 +986,28 @@ static int steam_register(struct steam_device *steam)
spin_lock_irqsave
(
&
steam
->
lock
,
flags
);
client_opened
=
steam
->
client_opened
;
spin_unlock_irqrestore
(
&
steam
->
lock
,
flags
);
if
(
!
client_opened
)
{
steam_set_lizard_mode
(
steam
,
lizard_mode
);
ret
=
steam_input_register
(
steam
);
}
else
ret
=
0
;
if
(
ret
!=
0
)
goto
steam_register_input_fail
;
ret
=
steam_sensors_register
(
steam
);
if
(
ret
!=
0
)
goto
steam_register_sensors_fail
;
}
return
0
;
steam_register_sensors_fail:
steam_input_unregister
(
steam
);
steam_register_input_fail:
return
ret
;
}
static
void
steam_unregister
(
struct
steam_device
*
steam
)
{
steam_battery_unregister
(
steam
);
steam_sensors_unregister
(
steam
);
steam_input_unregister
(
steam
);
if
(
steam
->
serial_no
[
0
])
{
hid_info
(
steam
->
hdev
,
"Steam Controller '%s' disconnected"
,
...
...
@@ -1010,6 +1116,7 @@ static int steam_client_ll_open(struct hid_device *hdev)
steam
->
client_opened
++
;
spin_unlock_irqrestore
(
&
steam
->
lock
,
flags
);
steam_sensors_unregister
(
steam
);
steam_input_unregister
(
steam
);
return
0
;
...
...
@@ -1030,6 +1137,7 @@ static void steam_client_ll_close(struct hid_device *hdev)
if
(
connected
)
{
steam_set_lizard_mode
(
steam
,
lizard_mode
);
steam_input_register
(
steam
);
steam_sensors_register
(
steam
);
}
}
...
...
@@ -1121,6 +1229,7 @@ static int steam_probe(struct hid_device *hdev,
INIT_DELAYED_WORK
(
&
steam
->
mode_switch
,
steam_mode_switch_cb
);
INIT_LIST_HEAD
(
&
steam
->
list
);
INIT_WORK
(
&
steam
->
rumble_work
,
steam_haptic_rumble_cb
);
steam
->
sensor_timestamp_us
=
0
;
/*
* With the real steam controller interface, do not connect hidraw.
...
...
@@ -1380,12 +1489,12 @@ static void steam_do_input_event(struct steam_device *steam,
* 18-19 | s16 | ABS_HAT0Y | left-pad Y value
* 20-21 | s16 | ABS_HAT1X | right-pad X value
* 22-23 | s16 | ABS_HAT1Y | right-pad Y value
* 24-25 | s16 |
--
| accelerometer X value
* 26-27 | s16 |
--
| accelerometer Y value
* 28-29 | s16 |
--
| accelerometer Z value
* 30-31 | s16 |
--
| gyro X value
* 32-33 | s16 |
--
| gyro Y value
* 34-35 | s16 |
--
| gyro Z value
* 24-25 | s16 |
IMU ABS_X
| accelerometer X value
* 26-27 | s16 |
IMU ABS_Z
| accelerometer Y value
* 28-29 | s16 |
IMU ABS_Y
| accelerometer Z value
* 30-31 | s16 |
IMU ABS_RX
| gyro X value
* 32-33 | s16 |
IMU ABS_RZ
| gyro Y value
* 34-35 | s16 |
IMU ABS_RY
| gyro Z value
* 36-37 | s16 | -- | quaternion W value
* 38-39 | s16 | -- | quaternion X value
* 40-41 | s16 | -- | quaternion Y value
...
...
@@ -1546,6 +1655,32 @@ static void steam_do_deck_input_event(struct steam_device *steam,
input_sync
(
input
);
}
static
void
steam_do_deck_sensors_event
(
struct
steam_device
*
steam
,
struct
input_dev
*
sensors
,
u8
*
data
)
{
/*
* The deck input report is received every 4 ms on average,
* with a jitter of +/- 4 ms even though the USB descriptor claims
* that it uses 1 kHz.
* Since the HID report does not include a sensor timestamp,
* use a fixed increment here.
*/
steam
->
sensor_timestamp_us
+=
4000
;
if
(
!
steam
->
gamepad_mode
)
return
;
input_event
(
sensors
,
EV_MSC
,
MSC_TIMESTAMP
,
steam
->
sensor_timestamp_us
);
input_report_abs
(
sensors
,
ABS_X
,
steam_le16
(
data
+
24
));
input_report_abs
(
sensors
,
ABS_Z
,
-
steam_le16
(
data
+
26
));
input_report_abs
(
sensors
,
ABS_Y
,
steam_le16
(
data
+
28
));
input_report_abs
(
sensors
,
ABS_RX
,
steam_le16
(
data
+
30
));
input_report_abs
(
sensors
,
ABS_RZ
,
-
steam_le16
(
data
+
32
));
input_report_abs
(
sensors
,
ABS_RY
,
steam_le16
(
data
+
34
));
input_sync
(
sensors
);
}
/*
* The size for this message payload is 11.
* The known values are:
...
...
@@ -1583,6 +1718,7 @@ static int steam_raw_event(struct hid_device *hdev,
{
struct
steam_device
*
steam
=
hid_get_drvdata
(
hdev
);
struct
input_dev
*
input
;
struct
input_dev
*
sensors
;
struct
power_supply
*
battery
;
if
(
!
steam
)
...
...
@@ -1628,6 +1764,9 @@ static int steam_raw_event(struct hid_device *hdev,
input
=
rcu_dereference
(
steam
->
input
);
if
(
likely
(
input
))
steam_do_deck_input_event
(
steam
,
input
,
data
);
sensors
=
rcu_dereference
(
steam
->
sensors
);
if
(
likely
(
sensors
))
steam_do_deck_sensors_event
(
steam
,
sensors
,
data
);
rcu_read_unlock
();
break
;
case
ID_CONTROLLER_WIRELESS
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment