Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4d3db6d2
Commit
4d3db6d2
authored
Oct 22, 2019
by
Andrew Eikum
Committed by
Alexandre Julliard
Oct 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
xinput: Make device hotplugging thread-safe.
Signed-off-by:
Andrew Eikum
<
aeikum@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c59e9d30
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
210 additions
and
131 deletions
+210
-131
hid.c
dlls/xinput1_3/hid.c
+117
-122
xinput_main.c
dlls/xinput1_3/xinput_main.c
+88
-7
xinput_private.h
dlls/xinput1_3/xinput_private.h
+5
-2
No files found.
dlls/xinput1_3/hid.c
View file @
4d3db6d2
...
...
@@ -47,15 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(xinput);
#define XINPUT_GAMEPAD_GUIDE 0x0400
static
CRITICAL_SECTION
hid_xinput_crit
;
static
CRITICAL_SECTION_DEBUG
hid_critsect_debug
=
{
0
,
0
,
&
hid_xinput_crit
,
{
&
hid_critsect_debug
.
ProcessLocksList
,
&
hid_critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": hid_xinput_crit"
)
}
};
static
CRITICAL_SECTION
hid_xinput_crit
=
{
&
hid_critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
struct
axis_info
{
LONG
min
;
...
...
@@ -69,8 +60,6 @@ struct hid_platform_private {
WCHAR
*
device_path
;
BOOL
enabled
;
CRITICAL_SECTION
crit
;
DWORD
report_length
;
BYTE
current_report
;
CHAR
*
reports
[
2
];
...
...
@@ -195,9 +184,6 @@ static void build_private(struct hid_platform_private *private, PHIDP_PREPARSED_
private
->
device_path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
memcpy
(
private
->
device_path
,
path
,
size
);
private
->
enabled
=
TRUE
;
InitializeCriticalSection
(
&
private
->
crit
);
private
->
crit
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": JoystickImpl*->generic.base.crit"
);
}
void
HID_find_gamepads
(
xinput_controller
*
devices
)
...
...
@@ -208,20 +194,26 @@ void HID_find_gamepads(xinput_controller *devices)
SP_DEVICE_INTERFACE_DETAIL_DATA_W
*
data
;
PHIDP_PREPARSED_DATA
ppd
;
DWORD
detail_size
=
MAX_PATH
*
sizeof
(
WCHAR
);
HANDLE
device
=
INVALID_HANDLE_VALUE
;
HANDLE
device
;
HIDP_CAPS
Caps
;
DWORD
idx
,
didx
;
int
i
;
DWORD
idx
;
int
i
,
open_device_idx
;
idx
=
GetTickCount
();
if
((
idx
-
last_check
)
<
2000
)
return
;
EnterCriticalSection
(
&
xinput_crit
);
if
((
idx
-
last_check
)
<
2000
)
{
LeaveCriticalSection
(
&
xinput_crit
);
return
;
}
last_check
=
idx
;
HidD_GetHidGuid
(
&
hid_guid
);
EnterCriticalSection
(
&
hid_xinput_crit
);
device_info_set
=
SetupDiGetClassDevsW
(
&
hid_guid
,
NULL
,
NULL
,
DIGCF_DEVICEINTERFACE
|
DIGCF_PRESENT
);
data
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
data
)
+
detail_size
);
...
...
@@ -230,9 +222,9 @@ void HID_find_gamepads(xinput_controller *devices)
ZeroMemory
(
&
interface_data
,
sizeof
(
interface_data
));
interface_data
.
cbSize
=
sizeof
(
interface_data
);
idx
=
didx
=
0
;
idx
=
0
;
while
(
SetupDiEnumDeviceInterfaces
(
device_info_set
,
NULL
,
&
hid_guid
,
idx
++
,
&
interface_data
)
&&
didx
<
XUSER_MAX_COUNT
)
&
interface_data
))
{
static
const
WCHAR
ig
[]
=
{
'I'
,
'G'
,
'_'
,
0
};
if
(
!
SetupDiGetDeviceInterfaceDetailW
(
device_info_set
,
...
...
@@ -242,14 +234,24 @@ void HID_find_gamepads(xinput_controller *devices)
if
(
!
wcsstr
(
data
->
DevicePath
,
ig
))
continue
;
open_device_idx
=
-
1
;
for
(
i
=
0
;
i
<
XUSER_MAX_COUNT
;
i
++
)
{
struct
hid_platform_private
*
private
=
devices
[
i
].
platform_private
;
if
(
devices
[
i
].
connected
&&
!
wcscmp
(
data
->
DevicePath
,
private
->
device_path
))
break
;
if
(
devices
[
i
].
connected
)
{
if
(
!
wcscmp
(
data
->
DevicePath
,
private
->
device_path
))
break
;
}
else
if
(
open_device_idx
<
0
)
open_device_idx
=
i
;
}
if
(
i
!=
XUSER_MAX_COUNT
)
/* this device is already opened */
continue
;
if
(
open_device_idx
<
0
)
/* no open device slots */
break
;
device
=
CreateFileW
(
data
->
DevicePath
,
GENERIC_READ
|
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
device
==
INVALID_HANDLE_VALUE
)
continue
;
...
...
@@ -262,13 +264,12 @@ void HID_find_gamepads(xinput_controller *devices)
Caps
.
Usage
==
0x8
/* Multi-axis Controller */
))
{
struct
hid_platform_private
*
private
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
struct
hid_platform_private
));
if
(
VerifyGamepad
(
ppd
,
&
(
devices
[
didx
].
caps
)
,
private
,
&
Caps
))
if
(
VerifyGamepad
(
ppd
,
&
devices
[
open_device_idx
].
caps
,
private
,
&
Caps
))
{
TRACE
(
"Found gamepad %i %s
\n
"
,
didx
,
debugstr_w
(
data
->
DevicePath
));
devices
[
didx
].
connected
=
TRUE
;
TRACE
(
"Found gamepad %i %s
\n
"
,
open_device_idx
,
debugstr_w
(
data
->
DevicePath
));
build_private
(
private
,
ppd
,
&
Caps
,
device
,
data
->
DevicePath
);
devices
[
d
idx
].
platform_private
=
private
;
d
idx
++
;
devices
[
open_device_
idx
].
platform_private
=
private
;
d
evices
[
open_device_idx
].
connected
=
TRUE
;
}
else
{
...
...
@@ -282,41 +283,39 @@ void HID_find_gamepads(xinput_controller *devices)
CloseHandle
(
device
);
HidD_FreePreparsedData
(
ppd
);
}
device
=
INVALID_HANDLE_VALUE
;
}
HeapFree
(
GetProcessHeap
(),
0
,
data
);
SetupDiDestroyDeviceInfoList
(
device_info_set
);
LeaveCriticalSection
(
&
hid_xinput_crit
);
return
;
LeaveCriticalSection
(
&
xinput_crit
);
}
static
void
remove_gamepad
(
xinput_controller
*
device
)
{
EnterCriticalSection
(
&
device
->
crit
);
if
(
device
->
connected
)
{
struct
hid_platform_private
*
private
=
device
->
platform_private
;
EnterCriticalSection
(
&
private
->
crit
);
device
->
connected
=
FALSE
;
CloseHandle
(
private
->
device
);
HeapFree
(
GetProcessHeap
(),
0
,
private
->
reports
[
0
]);
HeapFree
(
GetProcessHeap
(),
0
,
private
->
reports
[
1
]);
HeapFree
(
GetProcessHeap
(),
0
,
private
->
device_path
);
HidD_FreePreparsedData
(
private
->
ppd
);
device
->
platform_private
=
NULL
;
device
->
connected
=
FALSE
;
LeaveCriticalSection
(
&
private
->
crit
);
DeleteCriticalSection
(
&
private
->
crit
);
HeapFree
(
GetProcessHeap
(),
0
,
private
);
}
LeaveCriticalSection
(
&
device
->
crit
);
}
void
HID_destroy_gamepads
(
xinput_controller
*
devices
)
{
int
i
;
EnterCriticalSection
(
&
hid_xinput_crit
);
for
(
i
=
0
;
i
<
XUSER_MAX_COUNT
;
i
++
)
remove_gamepad
(
&
devices
[
i
]);
LeaveCriticalSection
(
&
hid_xinput_crit
);
}
static
SHORT
scale_short
(
LONG
value
,
const
struct
axis_info
*
axis
)
...
...
@@ -329,7 +328,7 @@ static BYTE scale_byte(LONG value, const struct axis_info *axis)
return
(((
ULONGLONG
)(
value
-
axis
->
min
))
*
0xff
)
/
axis
->
range
;
}
void
HID_update_state
(
xinput_controller
*
devic
e
)
void
HID_update_state
(
xinput_controller
*
device
,
XINPUT_STATE
*
stat
e
)
{
struct
hid_platform_private
*
private
=
device
->
platform_private
;
int
i
;
...
...
@@ -343,107 +342,107 @@ void HID_update_state(xinput_controller* device)
if
(
!
private
->
enabled
)
return
;
EnterCriticalSection
(
&
private
->
crit
);
if
(
!
HidD_GetInputReport
(
private
->
device
,
target_report
,
private
->
report_length
))
{
if
(
GetLastError
()
==
ERROR_ACCESS_DENIED
||
GetLastError
()
==
ERROR_INVALID_HANDLE
)
{
EnterCriticalSection
(
&
xinput_crit
);
remove_gamepad
(
device
);
LeaveCriticalSection
(
&
xinput_crit
);
}
else
ERR
(
"Failed to get Input Report (%x)
\n
"
,
GetLastError
());
LeaveCriticalSection
(
&
private
->
crit
);
return
;
}
if
(
memcmp
(
report
,
target_report
,
private
->
report_length
)
=
=
0
)
if
(
memcmp
(
report
,
target_report
,
private
->
report_length
)
!
=
0
)
{
LeaveCriticalSection
(
&
private
->
crit
);
return
;
}
private
->
current_report
=
(
private
->
current_report
+
1
)
%
2
;
private
->
current_report
=
(
private
->
current_report
+
1
)
%
2
;
device
->
state
.
dwPacketNumber
++
;
button_length
=
ARRAY_SIZE
(
buttons
);
HidP_GetUsages
(
HidP_Input
,
HID_USAGE_PAGE_BUTTON
,
0
,
buttons
,
&
button_length
,
private
->
ppd
,
target_report
,
private
->
report_length
);
device
->
state
.
dwPacketNumber
++
;
button_length
=
ARRAY_SIZE
(
buttons
);
HidP_GetUsages
(
HidP_Input
,
HID_USAGE_PAGE_BUTTON
,
0
,
buttons
,
&
button_length
,
private
->
ppd
,
target_report
,
private
->
report_length
);
device
->
state
.
Gamepad
.
wButtons
=
0
;
for
(
i
=
0
;
i
<
button_length
;
i
++
)
{
switch
(
buttons
[
i
])
device
->
state
.
Gamepad
.
wButtons
=
0
;
for
(
i
=
0
;
i
<
button_length
;
i
++
)
{
case
1
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_A
;
break
;
case
2
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_B
;
break
;
case
3
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_X
;
break
;
case
4
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_Y
;
break
;
case
5
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_LEFT_SHOULDER
;
break
;
case
6
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_RIGHT_SHOULDER
;
break
;
case
7
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_BACK
;
break
;
case
8
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_START
;
break
;
case
9
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_LEFT_THUMB
;
break
;
case
10
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_RIGHT_THUMB
;
break
;
case
11
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_GUIDE
;
break
;
switch
(
buttons
[
i
])
{
case
1
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_A
;
break
;
case
2
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_B
;
break
;
case
3
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_X
;
break
;
case
4
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_Y
;
break
;
case
5
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_LEFT_SHOULDER
;
break
;
case
6
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_RIGHT_SHOULDER
;
break
;
case
7
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_BACK
;
break
;
case
8
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_START
;
break
;
case
9
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_LEFT_THUMB
;
break
;
case
10
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_RIGHT_THUMB
;
break
;
case
11
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_GUIDE
;
break
;
}
}
}
if
(
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_HATSWITCH
,
&
hat_value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
{
switch
(
hat_value
){
/* 8 1 2
* 7 0 3
* 6 5 4 */
case
0
:
break
;
case
1
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_UP
;
break
;
case
2
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_UP
|
XINPUT_GAMEPAD_DPAD_RIGHT
;
break
;
case
3
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_RIGHT
;
break
;
case
4
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_RIGHT
|
XINPUT_GAMEPAD_DPAD_DOWN
;
break
;
case
5
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_DOWN
;
break
;
case
6
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_DOWN
|
XINPUT_GAMEPAD_DPAD_LEFT
;
break
;
case
7
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_LEFT
;
break
;
case
8
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_LEFT
|
XINPUT_GAMEPAD_DPAD_UP
;
break
;
if
(
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_HATSWITCH
,
&
hat_value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
{
switch
(
hat_value
){
/* 8 1 2
* 7 0 3
* 6 5 4 */
case
0
:
break
;
case
1
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_UP
;
break
;
case
2
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_UP
|
XINPUT_GAMEPAD_DPAD_RIGHT
;
break
;
case
3
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_RIGHT
;
break
;
case
4
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_RIGHT
|
XINPUT_GAMEPAD_DPAD_DOWN
;
break
;
case
5
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_DOWN
;
break
;
case
6
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_DOWN
|
XINPUT_GAMEPAD_DPAD_LEFT
;
break
;
case
7
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_LEFT
;
break
;
case
8
:
device
->
state
.
Gamepad
.
wButtons
|=
XINPUT_GAMEPAD_DPAD_LEFT
|
XINPUT_GAMEPAD_DPAD_UP
;
break
;
}
}
}
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_X
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbLX
=
scale_short
(
value
,
&
private
->
lx
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_X
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbLX
=
scale_short
(
value
,
&
private
->
lx
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Y
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbLY
=
-
scale_short
(
value
,
&
private
->
ly
)
-
1
;
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Y
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbLY
=
-
scale_short
(
value
,
&
private
->
ly
)
-
1
;
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RX
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbRX
=
scale_short
(
value
,
&
private
->
rx
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RX
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbRX
=
scale_short
(
value
,
&
private
->
rx
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RY
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbRY
=
-
scale_short
(
value
,
&
private
->
ry
)
-
1
;
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RY
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
sThumbRY
=
-
scale_short
(
value
,
&
private
->
ry
)
-
1
;
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RZ
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
bRightTrigger
=
scale_byte
(
value
,
&
private
->
rtrigger
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RZ
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
bRightTrigger
=
scale_byte
(
value
,
&
private
->
rtrigger
);
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Z
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
bLeftTrigger
=
scale_byte
(
value
,
&
private
->
ltrigger
);
}
if
(
HidP_GetScaledUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Z
,
&
value
,
private
->
ppd
,
target_report
,
private
->
report_length
)
==
HIDP_STATUS_SUCCESS
)
device
->
state
.
Gamepad
.
bLeftTrigger
=
scale_byte
(
value
,
&
private
->
ltrigger
);
LeaveCriticalSection
(
&
private
->
crit
);
memcpy
(
state
,
&
device
->
state
,
sizeof
(
*
state
));
}
DWORD
HID_set_state
(
xinput_controller
*
device
,
XINPUT_VIBRATION
*
state
)
...
...
@@ -474,9 +473,7 @@ DWORD HID_set_state(xinput_controller* device, XINPUT_VIBRATION* state)
report
.
right
=
(
BYTE
)(
state
->
wRightMotorSpeed
/
256
);
memset
(
&
report
.
pad2
,
0
,
sizeof
(
report
.
pad2
));
EnterCriticalSection
(
&
private
->
crit
);
rc
=
HidD_SetOutputReport
(
private
->
device
,
&
report
,
sizeof
(
report
));
LeaveCriticalSection
(
&
private
->
crit
);
if
(
rc
)
return
ERROR_SUCCESS
;
return
GetLastError
();
...
...
@@ -492,7 +489,6 @@ void HID_enable(xinput_controller* device, BOOL enable)
if
(
device
->
caps
.
Flags
&
XINPUT_CAPS_FFB_SUPPORTED
)
{
EnterCriticalSection
(
&
private
->
crit
);
if
(
private
->
enabled
&&
!
enable
)
{
XINPUT_VIBRATION
state
;
...
...
@@ -504,7 +500,6 @@ void HID_enable(xinput_controller* device, BOOL enable)
{
HID_set_state
(
device
,
&
device
->
vibration
);
}
LeaveCriticalSection
(
&
private
->
crit
);
}
private
->
enabled
=
enable
;
...
...
dlls/xinput1_3/xinput_main.c
View file @
4d3db6d2
...
...
@@ -34,7 +34,66 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
xinput
);
xinput_controller
controllers
[
XUSER_MAX_COUNT
];
/* xinput_crit guards controllers array */
static
CRITICAL_SECTION_DEBUG
xinput_critsect_debug
=
{
0
,
0
,
&
xinput_crit
,
{
&
xinput_critsect_debug
.
ProcessLocksList
,
&
xinput_critsect_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": xinput_crit"
)
}
};
CRITICAL_SECTION
xinput_crit
=
{
&
xinput_critsect_debug
,
-
1
,
0
,
0
,
0
,
0
};
static
CRITICAL_SECTION_DEBUG
controller_critsect_debug
[
XUSER_MAX_COUNT
]
=
{
{
0
,
0
,
&
controllers
[
0
].
crit
,
{
&
controller_critsect_debug
[
0
].
ProcessLocksList
,
&
controller_critsect_debug
[
0
].
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": controllers[0].crit"
)
}
},
{
0
,
0
,
&
controllers
[
1
].
crit
,
{
&
controller_critsect_debug
[
1
].
ProcessLocksList
,
&
controller_critsect_debug
[
1
].
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": controllers[1].crit"
)
}
},
{
0
,
0
,
&
controllers
[
2
].
crit
,
{
&
controller_critsect_debug
[
2
].
ProcessLocksList
,
&
controller_critsect_debug
[
2
].
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": controllers[2].crit"
)
}
},
{
0
,
0
,
&
controllers
[
3
].
crit
,
{
&
controller_critsect_debug
[
3
].
ProcessLocksList
,
&
controller_critsect_debug
[
3
].
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": controllers[3].crit"
)
}
},
};
xinput_controller
controllers
[
XUSER_MAX_COUNT
]
=
{
{{
&
controller_critsect_debug
[
0
],
-
1
,
0
,
0
,
0
,
0
}},
{{
&
controller_critsect_debug
[
1
],
-
1
,
0
,
0
,
0
,
0
}},
{{
&
controller_critsect_debug
[
2
],
-
1
,
0
,
0
,
0
,
0
}},
{{
&
controller_critsect_debug
[
3
],
-
1
,
0
,
0
,
0
,
0
}},
};
static
BOOL
verify_and_lock_device
(
xinput_controller
*
device
)
{
if
(
!
device
->
connected
)
return
FALSE
;
EnterCriticalSection
(
&
device
->
crit
);
if
(
!
device
->
connected
)
{
LeaveCriticalSection
(
&
device
->
crit
);
return
FALSE
;
}
return
TRUE
;
}
static
void
unlock_device
(
xinput_controller
*
device
)
{
LeaveCriticalSection
(
&
device
->
crit
);
}
BOOL
WINAPI
DllMain
(
HINSTANCE
inst
,
DWORD
reason
,
LPVOID
reserved
)
{
...
...
@@ -65,23 +124,30 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
for
(
index
=
0
;
index
<
XUSER_MAX_COUNT
;
index
++
)
{
if
(
!
controllers
[
index
].
connected
)
continue
;
if
(
!
verify_and_lock_device
(
&
controllers
[
index
])
)
continue
;
HID_enable
(
&
controllers
[
index
],
enable
);
unlock_device
(
&
controllers
[
index
]);
}
}
DWORD
WINAPI
DECLSPEC_HOTPATCH
XInputSetState
(
DWORD
index
,
XINPUT_VIBRATION
*
vibration
)
{
DWORD
ret
;
TRACE
(
"(index %u, vibration %p)
\n
"
,
index
,
vibration
);
HID_find_gamepads
(
controllers
);
if
(
index
>=
XUSER_MAX_COUNT
)
return
ERROR_BAD_ARGUMENTS
;
if
(
!
controllers
[
index
].
connected
)
if
(
!
verify_and_lock_device
(
&
controllers
[
index
])
)
return
ERROR_DEVICE_NOT_CONNECTED
;
return
HID_set_state
(
&
controllers
[
index
],
vibration
);
ret
=
HID_set_state
(
&
controllers
[
index
],
vibration
);
unlock_device
(
&
controllers
[
index
]);
return
ret
;
}
/* Some versions of SteamOverlayRenderer hot-patch XInputGetStateEx() and call
...
...
@@ -95,11 +161,19 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
if
(
index
>=
XUSER_MAX_COUNT
)
return
ERROR_BAD_ARGUMENTS
;
if
(
!
verify_and_lock_device
(
&
controllers
[
index
]))
return
ERROR_DEVICE_NOT_CONNECTED
;
HID_update_state
(
&
controllers
[
index
],
state
);
if
(
!
controllers
[
index
].
connected
)
{
/* update_state may have disconnected the controller */
unlock_device
(
&
controllers
[
index
]);
return
ERROR_DEVICE_NOT_CONNECTED
;
}
HID_update_state
(
&
controllers
[
index
]);
memcpy
(
state
,
&
controllers
[
index
].
state
,
sizeof
(
XINPUT_STATE
));
unlock_device
(
&
controllers
[
index
]);
return
ERROR_SUCCESS
;
}
...
...
@@ -151,13 +225,20 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, X
if
(
index
>=
XUSER_MAX_COUNT
)
return
ERROR_BAD_ARGUMENTS
;
if
(
!
controllers
[
index
].
connected
)
if
(
!
verify_and_lock_device
(
&
controllers
[
index
]))
return
ERROR_DEVICE_NOT_CONNECTED
;
if
(
flags
&
XINPUT_FLAG_GAMEPAD
&&
controllers
[
index
].
caps
.
SubType
!=
XINPUT_DEVSUBTYPE_GAMEPAD
)
{
unlock_device
(
&
controllers
[
index
]);
return
ERROR_DEVICE_NOT_CONNECTED
;
}
memcpy
(
capabilities
,
&
controllers
[
index
].
caps
,
sizeof
(
*
capabilities
));
unlock_device
(
&
controllers
[
index
]);
return
ERROR_SUCCESS
;
}
...
...
dlls/xinput1_3/xinput_private.h
View file @
4d3db6d2
...
...
@@ -19,16 +19,19 @@
typedef
struct
_xinput_controller
{
BOOL
connected
;
CRITICAL_SECTION
crit
;
BOOL
connected
;
/* only TRUE when device is valid; may be used without holding crit */
XINPUT_CAPABILITIES
caps
;
void
*
platform_private
;
XINPUT_STATE
state
;
XINPUT_VIBRATION
vibration
;
}
xinput_controller
;
CRITICAL_SECTION
xinput_crit
;
xinput_controller
controllers
[
XUSER_MAX_COUNT
];
void
HID_find_gamepads
(
xinput_controller
*
devices
)
DECLSPEC_HIDDEN
;
void
HID_destroy_gamepads
(
xinput_controller
*
devices
)
DECLSPEC_HIDDEN
;
void
HID_update_state
(
xinput_controller
*
device
)
DECLSPEC_HIDDEN
;
void
HID_update_state
(
xinput_controller
*
device
,
XINPUT_STATE
*
state
)
DECLSPEC_HIDDEN
;
DWORD
HID_set_state
(
xinput_controller
*
device
,
XINPUT_VIBRATION
*
state
)
DECLSPEC_HIDDEN
;
void
HID_enable
(
xinput_controller
*
device
,
BOOL
enable
)
DECLSPEC_HIDDEN
;
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