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
2eea1d61
Commit
2eea1d61
authored
Sep 10, 2021
by
Rémi Bernon
Committed by
Alexandre Julliard
Sep 10, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winexinput.sys: Translate lower reports into XInput HID reports.
Signed-off-by:
Rémi Bernon
<
rbernon@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
b027f70a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
349 additions
and
32 deletions
+349
-32
main.c
dlls/winexinput.sys/main.c
+181
-7
pop_hid_macros.h
dlls/winexinput.sys/pop_hid_macros.h
+83
-0
psh_hid_macros.h
dlls/winexinput.sys/psh_hid_macros.h
+85
-0
xinput.c
dlls/xinput1_3/tests/xinput.c
+0
-25
No files found.
dlls/winexinput.sys/main.c
View file @
2eea1d61
...
@@ -50,6 +50,75 @@ __ASM_STDCALL_FUNC(wrap_fastcall_func1, 8,
...
@@ -50,6 +50,75 @@ __ASM_STDCALL_FUNC(wrap_fastcall_func1, 8,
#define call_fastcall_func1(func,a) func(a)
#define call_fastcall_func1(func,a) func(a)
#endif
#endif
#include "psh_hid_macros.h"
const
BYTE
xinput_report_desc
[]
=
{
USAGE_PAGE
(
1
,
HID_USAGE_PAGE_GENERIC
),
USAGE
(
1
,
HID_USAGE_GENERIC_GAMEPAD
),
COLLECTION
(
1
,
Application
),
USAGE
(
1
,
0
),
COLLECTION
(
1
,
Physical
),
USAGE
(
1
,
HID_USAGE_GENERIC_X
),
USAGE
(
1
,
HID_USAGE_GENERIC_Y
),
LOGICAL_MAXIMUM
(
2
,
0xffff
),
PHYSICAL_MAXIMUM
(
2
,
0xffff
),
REPORT_SIZE
(
1
,
16
),
REPORT_COUNT
(
1
,
2
),
INPUT
(
1
,
Data
|
Var
|
Abs
),
END_COLLECTION
,
COLLECTION
(
1
,
Physical
),
USAGE
(
1
,
HID_USAGE_GENERIC_RX
),
USAGE
(
1
,
HID_USAGE_GENERIC_RY
),
REPORT_COUNT
(
1
,
2
),
INPUT
(
1
,
Data
|
Var
|
Abs
),
END_COLLECTION
,
COLLECTION
(
1
,
Physical
),
USAGE
(
1
,
HID_USAGE_GENERIC_Z
),
REPORT_COUNT
(
1
,
1
),
INPUT
(
1
,
Data
|
Var
|
Abs
),
END_COLLECTION
,
USAGE_PAGE
(
1
,
HID_USAGE_PAGE_BUTTON
),
USAGE_MINIMUM
(
1
,
1
),
USAGE_MAXIMUM
(
1
,
10
),
LOGICAL_MAXIMUM
(
1
,
1
),
PHYSICAL_MAXIMUM
(
1
,
1
),
REPORT_COUNT
(
1
,
10
),
REPORT_SIZE
(
1
,
1
),
INPUT
(
1
,
Data
|
Var
|
Abs
),
USAGE_PAGE
(
1
,
HID_USAGE_PAGE_GENERIC
),
USAGE
(
1
,
HID_USAGE_GENERIC_HATSWITCH
),
LOGICAL_MINIMUM
(
1
,
1
),
LOGICAL_MAXIMUM
(
1
,
8
),
PHYSICAL_MAXIMUM
(
2
,
0x103b
),
REPORT_SIZE
(
1
,
4
),
REPORT_COUNT
(
4
,
1
),
UNIT
(
1
,
0x0e
/* none */
),
INPUT
(
1
,
Data
|
Var
|
Abs
|
Null
),
REPORT_COUNT
(
1
,
18
),
REPORT_SIZE
(
1
,
1
),
INPUT
(
1
,
Cnst
|
Var
|
Abs
),
END_COLLECTION
,
};
#include "pop_hid_macros.h"
struct
xinput_state
{
WORD
lx_axis
;
WORD
ly_axis
;
WORD
rx_axis
;
WORD
ry_axis
;
WORD
trigger
;
WORD
buttons
;
WORD
padding
;
};
struct
device
struct
device
{
{
BOOL
is_fdo
;
BOOL
is_fdo
;
...
@@ -96,6 +165,7 @@ struct func_device
...
@@ -96,6 +165,7 @@ struct func_device
char
*
report_buf
;
char
*
report_buf
;
IRP
*
pending_read
;
IRP
*
pending_read
;
BOOL
pending_is_gamepad
;
BOOL
pending_is_gamepad
;
struct
xinput_state
xinput_state
;
};
};
static
inline
struct
func_device
*
fdo_from_DEVICE_OBJECT
(
DEVICE_OBJECT
*
device
)
static
inline
struct
func_device
*
fdo_from_DEVICE_OBJECT
(
DEVICE_OBJECT
*
device
)
...
@@ -105,6 +175,73 @@ static inline struct func_device *fdo_from_DEVICE_OBJECT(DEVICE_OBJECT *device)
...
@@ -105,6 +175,73 @@ static inline struct func_device *fdo_from_DEVICE_OBJECT(DEVICE_OBJECT *device)
else
return
CONTAINING_RECORD
(
impl
,
struct
phys_device
,
base
)
->
fdo
;
else
return
CONTAINING_RECORD
(
impl
,
struct
phys_device
,
base
)
->
fdo
;
}
}
static
LONG
sign_extend
(
ULONG
value
,
const
HIDP_VALUE_CAPS
*
caps
)
{
UINT
sign
=
1
<<
(
caps
->
BitSize
-
1
);
if
(
sign
<=
1
||
caps
->
LogicalMin
>=
0
)
return
value
;
return
value
-
((
value
&
sign
)
<<
1
);
}
static
LONG
scale_value
(
ULONG
value
,
const
HIDP_VALUE_CAPS
*
caps
,
LONG
min
,
LONG
max
)
{
LONG
tmp
=
sign_extend
(
value
,
caps
);
if
(
caps
->
LogicalMin
>
caps
->
LogicalMax
)
return
0
;
if
(
caps
->
LogicalMin
>
tmp
||
caps
->
LogicalMax
<
tmp
)
return
0
;
return
min
+
MulDiv
(
tmp
-
caps
->
LogicalMin
,
max
-
min
,
caps
->
LogicalMax
-
caps
->
LogicalMin
);
}
static
void
translate_report_to_xinput_state
(
struct
func_device
*
fdo
)
{
ULONG
lx
=
0
,
ly
=
0
,
rx
=
0
,
ry
=
0
,
lt
=
0
,
rt
=
0
,
hat
=
0
;
PHIDP_PREPARSED_DATA
preparsed
;
USAGE
usages
[
10
];
NTSTATUS
status
;
ULONG
i
,
count
;
preparsed
=
fdo
->
device_desc
.
CollectionDesc
->
PreparsedData
;
count
=
ARRAY_SIZE
(
usages
);
status
=
HidP_GetUsages
(
HidP_Input
,
HID_USAGE_PAGE_BUTTON
,
0
,
usages
,
&
count
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsages returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_HATSWITCH
,
&
hat
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue hat returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_X
,
&
lx
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue x returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Y
,
&
ly
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue y returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Z
,
&
lt
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue z returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RX
,
&
rx
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue rx returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RY
,
&
ry
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue ry returned %#x
\n
"
,
status
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RZ
,
&
rt
,
preparsed
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
WARN
(
"HidP_GetUsageValue rz returned %#x
\n
"
,
status
);
if
(
hat
<
1
||
hat
>
8
)
fdo
->
xinput_state
.
buttons
=
0
;
else
fdo
->
xinput_state
.
buttons
=
hat
<<
10
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
usages
[
i
]
<
1
||
usages
[
i
]
>
10
)
continue
;
fdo
->
xinput_state
.
buttons
|=
(
1
<<
(
usages
[
i
]
-
1
));
}
fdo
->
xinput_state
.
lx_axis
=
scale_value
(
lx
,
&
fdo
->
lx_caps
,
0
,
65535
);
fdo
->
xinput_state
.
ly_axis
=
scale_value
(
ly
,
&
fdo
->
ly_caps
,
0
,
65535
);
fdo
->
xinput_state
.
rx_axis
=
scale_value
(
rx
,
&
fdo
->
rx_caps
,
0
,
65535
);
fdo
->
xinput_state
.
ry_axis
=
scale_value
(
ry
,
&
fdo
->
ry_caps
,
0
,
65535
);
rt
=
scale_value
(
rt
,
&
fdo
->
rt_caps
,
0
,
255
);
lt
=
scale_value
(
lt
,
&
fdo
->
lt_caps
,
0
,
255
);
fdo
->
xinput_state
.
trigger
=
0x8000
+
(
lt
-
rt
)
*
128
;
}
static
NTSTATUS
WINAPI
read_completion
(
DEVICE_OBJECT
*
device
,
IRP
*
xinput_irp
,
void
*
context
)
static
NTSTATUS
WINAPI
read_completion
(
DEVICE_OBJECT
*
device
,
IRP
*
xinput_irp
,
void
*
context
)
{
{
IO_STACK_LOCATION
*
stack
=
IoGetCurrentIrpStackLocation
(
xinput_irp
);
IO_STACK_LOCATION
*
stack
=
IoGetCurrentIrpStackLocation
(
xinput_irp
);
...
@@ -121,7 +258,9 @@ static NTSTATUS WINAPI read_completion(DEVICE_OBJECT *device, IRP *xinput_irp, v
...
@@ -121,7 +258,9 @@ static NTSTATUS WINAPI read_completion(DEVICE_OBJECT *device, IRP *xinput_irp, v
RtlEnterCriticalSection
(
&
fdo
->
cs
);
RtlEnterCriticalSection
(
&
fdo
->
cs
);
offset
=
fdo
->
report_buf
[
0
]
?
0
:
1
;
offset
=
fdo
->
report_buf
[
0
]
?
0
:
1
;
memcpy
(
fdo
->
report_buf
+
offset
,
read_buf
,
read_len
);
memcpy
(
fdo
->
report_buf
+
offset
,
read_buf
,
read_len
);
memcpy
(
gamepad_irp
->
UserBuffer
,
read_buf
,
read_len
);
translate_report_to_xinput_state
(
fdo
);
memcpy
(
gamepad_irp
->
UserBuffer
,
&
fdo
->
xinput_state
,
sizeof
(
fdo
->
xinput_state
));
gamepad_irp
->
IoStatus
.
Information
=
sizeof
(
fdo
->
xinput_state
);
RtlLeaveCriticalSection
(
&
fdo
->
cs
);
RtlLeaveCriticalSection
(
&
fdo
->
cs
);
}
}
...
@@ -178,6 +317,7 @@ static NTSTATUS try_complete_pending_read(DEVICE_OBJECT *device, IRP *irp)
...
@@ -178,6 +317,7 @@ static NTSTATUS try_complete_pending_read(DEVICE_OBJECT *device, IRP *irp)
static
NTSTATUS
WINAPI
gamepad_internal_ioctl
(
DEVICE_OBJECT
*
device
,
IRP
*
irp
)
static
NTSTATUS
WINAPI
gamepad_internal_ioctl
(
DEVICE_OBJECT
*
device
,
IRP
*
irp
)
{
{
IO_STACK_LOCATION
*
stack
=
IoGetCurrentIrpStackLocation
(
irp
);
IO_STACK_LOCATION
*
stack
=
IoGetCurrentIrpStackLocation
(
irp
);
ULONG
output_len
=
stack
->
Parameters
.
DeviceIoControl
.
OutputBufferLength
;
ULONG
code
=
stack
->
Parameters
.
DeviceIoControl
.
IoControlCode
;
ULONG
code
=
stack
->
Parameters
.
DeviceIoControl
.
IoControlCode
;
struct
func_device
*
fdo
=
fdo_from_DEVICE_OBJECT
(
device
);
struct
func_device
*
fdo
=
fdo_from_DEVICE_OBJECT
(
device
);
...
@@ -185,20 +325,54 @@ static NTSTATUS WINAPI gamepad_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
...
@@ -185,20 +325,54 @@ static NTSTATUS WINAPI gamepad_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
switch
(
code
)
switch
(
code
)
{
{
case
IOCTL_HID_GET_
INPUT_REPORT
:
case
IOCTL_HID_GET_
DEVICE_DESCRIPTOR
:
{
{
HID_
XFER_PACKET
*
packet
=
(
HID_XFER_PACKET
*
)
irp
->
UserBuffer
;
HID_
DESCRIPTOR
*
descriptor
=
(
HID_DESCRIPTOR
*
)
irp
->
UserBuffer
;
RtlEnterCriticalSection
(
&
fdo
->
cs
);
irp
->
IoStatus
.
Information
=
sizeof
(
*
descriptor
);
memcpy
(
packet
->
reportBuffer
,
fdo
->
report_buf
,
fdo
->
report_len
);
if
(
output_len
<
sizeof
(
*
descriptor
))
irp
->
IoStatus
.
Information
=
fdo
->
report_len
;
{
RtlLeaveCriticalSection
(
&
fdo
->
cs
);
irp
->
IoStatus
.
Status
=
STATUS_BUFFER_TOO_SMALL
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
return
STATUS_BUFFER_TOO_SMALL
;
}
memset
(
descriptor
,
0
,
sizeof
(
*
descriptor
));
descriptor
->
bLength
=
sizeof
(
*
descriptor
);
descriptor
->
bDescriptorType
=
HID_HID_DESCRIPTOR_TYPE
;
descriptor
->
bcdHID
=
HID_REVISION
;
descriptor
->
bCountry
=
0
;
descriptor
->
bNumDescriptors
=
1
;
descriptor
->
DescriptorList
[
0
].
bReportType
=
HID_REPORT_DESCRIPTOR_TYPE
;
descriptor
->
DescriptorList
[
0
].
wReportLength
=
sizeof
(
xinput_report_desc
);
irp
->
IoStatus
.
Status
=
STATUS_SUCCESS
;
irp
->
IoStatus
.
Status
=
STATUS_SUCCESS
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
return
STATUS_SUCCESS
;
return
STATUS_SUCCESS
;
}
}
case
IOCTL_HID_GET_REPORT_DESCRIPTOR
:
irp
->
IoStatus
.
Information
=
sizeof
(
xinput_report_desc
);
if
(
output_len
<
sizeof
(
xinput_report_desc
))
{
irp
->
IoStatus
.
Status
=
STATUS_BUFFER_TOO_SMALL
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
return
STATUS_BUFFER_TOO_SMALL
;
}
memcpy
(
irp
->
UserBuffer
,
xinput_report_desc
,
sizeof
(
xinput_report_desc
));
irp
->
IoStatus
.
Status
=
STATUS_SUCCESS
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
return
STATUS_SUCCESS
;
case
IOCTL_HID_GET_INPUT_REPORT
:
case
IOCTL_HID_SET_OUTPUT_REPORT
:
case
IOCTL_HID_GET_FEATURE
:
case
IOCTL_HID_SET_FEATURE
:
irp
->
IoStatus
.
Status
=
STATUS_INVALID_PARAMETER
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
return
STATUS_INVALID_PARAMETER
;
default:
default:
IoSkipCurrentIrpStackLocation
(
irp
);
IoSkipCurrentIrpStackLocation
(
irp
);
return
IoCallDriver
(
fdo
->
bus_device
,
irp
);
return
IoCallDriver
(
fdo
->
bus_device
,
irp
);
...
...
dlls/winexinput.sys/pop_hid_macros.h
0 → 100644
View file @
2eea1d61
/*
* HID report helper macros.
*
* Copyright 2021 Rémi Bernon for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#undef Data
#undef Cnst
#undef Array
#undef Var
#undef Abs
#undef Rel
#undef NoWrap
#undef Wrap
#undef NonLin
#undef Lin
#undef NoPref
#undef Pref
#undef NoNull
#undef Null
#undef NonVol
#undef Vol
#undef Bits
#undef Buff
#undef Physical
#undef Application
#undef Logical
#undef Report
#undef NamedArray
#undef UsageSwitch
#undef UsageModifier
#undef SHORT_ITEM_0
#undef SHORT_ITEM_1
#undef SHORT_ITEM_2
#undef SHORT_ITEM_4
#undef LONG_ITEM
#undef INPUT
#undef OUTPUT
#undef FEATURE
#undef COLLECTION
#undef END_COLLECTION
#undef USAGE_PAGE
#undef LOGICAL_MINIMUM
#undef LOGICAL_MAXIMUM
#undef PHYSICAL_MINIMUM
#undef PHYSICAL_MAXIMUM
#undef UNIT_EXPONENT
#undef UNIT
#undef REPORT_SIZE
#undef REPORT_ID
#undef REPORT_COUNT
#undef PUSH
#undef POP
#undef USAGE
#undef USAGE_MINIMUM
#undef USAGE_MAXIMUM
#undef DESIGNATOR_INDEX
#undef DESIGNATOR_MINIMUM
#undef DESIGNATOR_MAXIMUM
#undef STRING_INDEX
#undef STRING_MINIMUM
#undef STRING_MAXIMUM
#undef DELIMITER
dlls/winexinput.sys/psh_hid_macros.h
0 → 100644
View file @
2eea1d61
/*
* HID report helper macros.
*
* Copyright 2021 Rémi Bernon for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <hidusage.h>
#define Data 0
#define Cnst 0x01
#define Ary 0
#define Var 0x02
#define Abs 0
#define Rel 0x04
#define NoWrap 0
#define Wrap 0x08
#define NonLin 0
#define Lin 0x10
#define NoPref 0
#define Pref 0x20
#define NoNull 0
#define Null 0x40
#define NonVol 0
#define Vol 0x80
#define Bits 0
#define Buff 0x100
#define Physical 0x00
#define Application 0x01
#define Logical 0x02
#define Report 0x03
#define NamedArray 0x04
#define UsageSwitch 0x05
#define UsageModifier 0x06
#define SHORT_ITEM_0(tag,type) (((tag)<<4)|((type)<<2)|0)
#define SHORT_ITEM_1(tag,type,data) (((tag)<<4)|((type)<<2)|1),((data)&0xff)
#define SHORT_ITEM_2(tag,type,data) (((tag)<<4)|((type)<<2)|2),((data)&0xff),(((data)>>8)&0xff)
#define SHORT_ITEM_4(tag,type,data) (((tag)<<4)|((type)<<2)|3),((data)&0xff),(((data)>>8)&0xff),(((data)>>16)&0xff),(((data)>>24)&0xff)
#define LONG_ITEM(tag,size) SHORT_ITEM_2(0xf,0x3,((tag)<<8)|(size))
#define INPUT(n,data) SHORT_ITEM_##n(0x8,0,data)
#define OUTPUT(n,data) SHORT_ITEM_##n(0x9,0,data)
#define FEATURE(n,data) SHORT_ITEM_##n(0xb,0,data)
#define COLLECTION(n,data) SHORT_ITEM_##n(0xa,0,data)
#define END_COLLECTION SHORT_ITEM_0(0xc,0)
#define USAGE_PAGE(n,data) SHORT_ITEM_##n(0x0,1,data)
#define LOGICAL_MINIMUM(n,data) SHORT_ITEM_##n(0x1,1,data)
#define LOGICAL_MAXIMUM(n,data) SHORT_ITEM_##n(0x2,1,data)
#define PHYSICAL_MINIMUM(n,data) SHORT_ITEM_##n(0x3,1,data)
#define PHYSICAL_MAXIMUM(n,data) SHORT_ITEM_##n(0x4,1,data)
#define UNIT_EXPONENT(n,data) SHORT_ITEM_##n(0x5,1,data)
#define UNIT(n,data) SHORT_ITEM_##n(0x6,1,data)
#define REPORT_SIZE(n,data) SHORT_ITEM_##n(0x7,1,data)
#define REPORT_ID(n,data) SHORT_ITEM_##n(0x8,1,data)
#define REPORT_COUNT(n,data) SHORT_ITEM_##n(0x9,1,data)
#define PUSH(n,data) SHORT_ITEM_##n(0xa,1,data)
#define POP(n,data) SHORT_ITEM_##n(0xb,1,data)
#define USAGE(n,data) SHORT_ITEM_##n(0x0,2,data)
#define USAGE_MINIMUM(n,data) SHORT_ITEM_##n(0x1,2,data)
#define USAGE_MAXIMUM(n,data) SHORT_ITEM_##n(0x2,2,data)
#define DESIGNATOR_INDEX(n,data) SHORT_ITEM_##n(0x3,2,data)
#define DESIGNATOR_MINIMUM(n,data) SHORT_ITEM_##n(0x4,2,data)
#define DESIGNATOR_MAXIMUM(n,data) SHORT_ITEM_##n(0x5,2,data)
#define STRING_INDEX(n,data) SHORT_ITEM_##n(0x6,2,data)
#define STRING_MINIMUM(n,data) SHORT_ITEM_##n(0x7,2,data)
#define STRING_MAXIMUM(n,data) SHORT_ITEM_##n(0x8,2,data)
#define DELIMITER(n,data) SHORT_ITEM_##n(0x9,2,data)
dlls/xinput1_3/tests/xinput.c
View file @
2eea1d61
...
@@ -455,21 +455,15 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -455,21 +455,15 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%04x"
,
Usage
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%04x"
,
Usage
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%04x"
,
UsagePage
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%04x"
,
UsagePage
);
todo_wine
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
InputReportByteLength
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
InputReportByteLength
);
todo_wine_if
(
xi_caps
.
Flags
&
XINPUT_CAPS_FFB_SUPPORTED
)
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
OutputReportByteLength
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
OutputReportByteLength
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
FeatureReportByteLength
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
FeatureReportByteLength
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberLinkCollectionNodes
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberLinkCollectionNodes
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputButtonCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputButtonCaps
);
todo_wine
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputValueCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputValueCaps
);
todo_wine
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputDataIndices
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberInputDataIndices
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputButtonCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputButtonCaps
);
todo_wine_if
(
xi_caps
.
Flags
&
XINPUT_CAPS_FFB_SUPPORTED
)
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputValueCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputValueCaps
);
todo_wine_if
(
xi_caps
.
Flags
&
XINPUT_CAPS_FFB_SUPPORTED
)
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputDataIndices
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberOutputDataIndices
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberFeatureButtonCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberFeatureButtonCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberFeatureValueCaps
);
check_member
(
*
hid_caps
,
expect_hid_caps
,
"%d"
,
NumberFeatureValueCaps
);
...
@@ -522,11 +516,8 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -522,11 +516,8 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
else
if
(
button_caps
[
i
].
IsRange
&&
expect_button_caps
[
i
].
IsRange
)
else
if
(
button_caps
[
i
].
IsRange
&&
expect_button_caps
[
i
].
IsRange
)
{
{
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%04x"
,
Range
.
UsageMin
);
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%04x"
,
Range
.
UsageMin
);
todo_wine
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%04x"
,
Range
.
UsageMax
);
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%04x"
,
Range
.
UsageMax
);
todo_wine
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%d"
,
Range
.
DataIndexMin
);
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%d"
,
Range
.
DataIndexMin
);
todo_wine
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%d"
,
Range
.
DataIndexMax
);
check_member
(
button_caps
[
i
],
expect_button_caps
[
i
],
"%d"
,
Range
.
DataIndexMax
);
}
}
...
@@ -551,7 +542,6 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -551,7 +542,6 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
count
=
hid_caps
->
NumberInputValueCaps
;
count
=
hid_caps
->
NumberInputValueCaps
;
status
=
HidP_GetValueCaps
(
HidP_Input
,
value_caps
,
&
count
,
preparsed
);
status
=
HidP_GetValueCaps
(
HidP_Input
,
value_caps
,
&
count
,
preparsed
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetValueCaps returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetValueCaps returned %#x
\n
"
,
status
);
todo_wine
ok
(
count
==
ARRAY_SIZE
(
expect_value_caps
),
"got %d value caps
\n
"
,
count
);
ok
(
count
==
ARRAY_SIZE
(
expect_value_caps
),
"got %d value caps
\n
"
,
count
);
for
(
i
=
0
;
i
<
min
(
count
,
ARRAY_SIZE
(
expect_value_caps
));
++
i
)
for
(
i
=
0
;
i
<
min
(
count
,
ARRAY_SIZE
(
expect_value_caps
));
++
i
)
...
@@ -560,11 +550,8 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -560,11 +550,8 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%04x"
,
UsagePage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%04x"
,
UsagePage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
ReportID
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
ReportID
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsAlias
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsAlias
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
BitField
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
BitField
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkCollection
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkCollection
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkUsage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkUsage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkUsagePage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LinkUsagePage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsRange
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsRange
);
...
@@ -572,27 +559,19 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -572,27 +559,19 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsDesignatorRange
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsDesignatorRange
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsAbsolute
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
IsAbsolute
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
HasNull
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
HasNull
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
BitSize
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
BitSize
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
ReportCount
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
ReportCount
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
UnitsExp
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
UnitsExp
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
Units
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
Units
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LogicalMin
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LogicalMin
);
todo_wine
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LogicalMax
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
LogicalMax
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
PhysicalMin
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
PhysicalMin
);
todo_wine
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
PhysicalMax
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
PhysicalMax
);
if
(
!
value_caps
[
i
].
IsRange
&&
!
expect_value_caps
[
i
].
IsRange
)
if
(
!
value_caps
[
i
].
IsRange
&&
!
expect_value_caps
[
i
].
IsRange
)
{
{
todo_wine_if
(
i
>=
4
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%04x"
,
NotRange
.
Usage
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%04x"
,
NotRange
.
Usage
);
todo_wine_if
(
i
==
5
)
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
NotRange
.
DataIndex
);
check_member
(
value_caps
[
i
],
expect_value_caps
[
i
],
"%d"
,
NotRange
.
DataIndex
);
}
}
else
if
(
value_caps
[
i
].
IsRange
&&
expect_value_caps
[
i
].
IsRange
)
else
if
(
value_caps
[
i
].
IsRange
&&
expect_value_caps
[
i
].
IsRange
)
...
@@ -627,9 +606,7 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -627,9 +606,7 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
SetLastError
(
0xdeadbeef
);
SetLastError
(
0xdeadbeef
);
memset
(
buffer
,
0
,
sizeof
(
buffer
));
memset
(
buffer
,
0
,
sizeof
(
buffer
));
ret
=
HidD_GetInputReport
(
device
,
buffer
,
hid_caps
->
InputReportByteLength
);
ret
=
HidD_GetInputReport
(
device
,
buffer
,
hid_caps
->
InputReportByteLength
);
todo_wine
ok
(
!
ret
,
"HidD_GetInputReport succeeded
\n
"
);
ok
(
!
ret
,
"HidD_GetInputReport succeeded
\n
"
);
todo_wine
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"HidD_GetInputReport returned error %u
\n
"
,
GetLastError
());
ok
(
GetLastError
()
==
ERROR_INVALID_PARAMETER
,
"HidD_GetInputReport returned error %u
\n
"
,
GetLastError
());
if
(
!
winetest_interactive
)
skip
(
"skipping interactive tests
\n
"
);
if
(
!
winetest_interactive
)
skip
(
"skipping interactive tests
\n
"
);
...
@@ -737,12 +714,10 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
...
@@ -737,12 +714,10 @@ static void check_hid_caps(DWORD index, HANDLE device, PHIDP_PREPARSED_DATA pre
value
=
0
;
value
=
0
;
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Z
,
&
value
,
preparsed
,
buffer
,
hid_caps
->
InputReportByteLength
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_Z
,
&
value
,
preparsed
,
buffer
,
hid_caps
->
InputReportByteLength
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetUsageValue returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetUsageValue returned %#x
\n
"
,
status
);
todo_wine
ok
(
value
==
32768
+
(
state
.
Gamepad
.
bLeftTrigger
-
state
.
Gamepad
.
bRightTrigger
)
*
128
,
"got Z value %d (RT %d, LT %d)
\n
"
,
ok
(
value
==
32768
+
(
state
.
Gamepad
.
bLeftTrigger
-
state
.
Gamepad
.
bRightTrigger
)
*
128
,
"got Z value %d (RT %d, LT %d)
\n
"
,
value
,
state
.
Gamepad
.
bRightTrigger
,
state
.
Gamepad
.
bLeftTrigger
);
value
,
state
.
Gamepad
.
bRightTrigger
,
state
.
Gamepad
.
bLeftTrigger
);
value
=
0
;
value
=
0
;
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RZ
,
&
value
,
preparsed
,
buffer
,
hid_caps
->
InputReportByteLength
);
status
=
HidP_GetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
HID_USAGE_GENERIC_RZ
,
&
value
,
preparsed
,
buffer
,
hid_caps
->
InputReportByteLength
);
todo_wine
ok
(
status
==
HIDP_STATUS_USAGE_NOT_FOUND
,
"HidP_GetUsageValue returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_USAGE_NOT_FOUND
,
"HidP_GetUsageValue returned %#x
\n
"
,
status
);
}
while
(
ret
&&
(
state
.
Gamepad
.
bRightTrigger
!=
255
||
state
.
Gamepad
.
bLeftTrigger
!=
255
));
}
while
(
ret
&&
(
state
.
Gamepad
.
bRightTrigger
!=
255
||
state
.
Gamepad
.
bLeftTrigger
!=
255
));
}
}
...
...
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