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
a05b67b7
Commit
a05b67b7
authored
Feb 13, 2024
by
Rémi Bernon
Committed by
Alexandre Julliard
Feb 14, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mouhid.sys: Request preparsed data and inspect device caps.
parent
0ed830ea
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
120 additions
and
2 deletions
+120
-2
device8.c
dlls/dinput/tests/device8.c
+0
-1
Makefile.in
dlls/mouhid.sys/Makefile.in
+1
-1
main.c
dlls/mouhid.sys/main.c
+119
-0
No files found.
dlls/dinput/tests/device8.c
View file @
a05b67b7
...
...
@@ -1906,7 +1906,6 @@ static void test_hid_touch_screen(void)
.
report_id
=
1
,
.
report_len
=
2
,
.
report_buf
=
{
1
,
0x02
},
.
todo
=
TRUE
,
};
RAWINPUTDEVICE
rawdevice
=
{.
usUsagePage
=
HID_USAGE_PAGE_DIGITIZER
,
.
usUsage
=
HID_USAGE_DIGITIZER_TOUCH_SCREEN
};
...
...
dlls/mouhid.sys/Makefile.in
View file @
a05b67b7
MODULE
=
mouhid.sys
IMPORTS
=
ntoskrnl
IMPORTS
=
ntoskrnl
hidparse
EXTRADLLFLAGS
=
-Wl
,--subsystem,native
SOURCES
=
\
...
...
dlls/mouhid.sys/main.c
View file @
a05b67b7
...
...
@@ -42,6 +42,13 @@ struct device
{
LONG
removed
;
DEVICE_OBJECT
*
bus_device
;
PHIDP_PREPARSED_DATA
preparsed
;
ULONG
caps_count
;
ULONG
contact_max
;
HIDP_VALUE_CAPS
*
id_caps
;
HIDP_VALUE_CAPS
*
x_caps
;
HIDP_VALUE_CAPS
*
y_caps
;
};
static
inline
struct
device
*
impl_from_DEVICE_OBJECT
(
DEVICE_OBJECT
*
device
)
...
...
@@ -49,6 +56,21 @@ static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device )
return
(
struct
device
*
)
device
->
DeviceExtension
;
}
static
inline
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
inline
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
NTSTATUS
WINAPI
driver_ioctl
(
DEVICE_OBJECT
*
device
,
IRP
*
irp
)
{
IO_STACK_LOCATION
*
stack
=
IoGetCurrentIrpStackLocation
(
irp
);
...
...
@@ -69,6 +91,98 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp )
return
IoCallDriver
(
impl
->
bus_device
,
irp
);
}
static
NTSTATUS
call_hid_device
(
DEVICE_OBJECT
*
device
,
DWORD
major
,
DWORD
code
,
void
*
in_buf
,
DWORD
in_len
,
void
*
out_buf
,
DWORD
out_len
)
{
struct
device
*
impl
=
impl_from_DEVICE_OBJECT
(
device
);
IO_STATUS_BLOCK
io
;
NTSTATUS
status
;
KEVENT
event
;
IRP
*
irp
;
KeInitializeEvent
(
&
event
,
NotificationEvent
,
FALSE
);
irp
=
IoBuildDeviceIoControlRequest
(
code
,
device
,
in_buf
,
in_len
,
out_buf
,
out_len
,
FALSE
,
&
event
,
&
io
);
if
(
!
irp
)
return
STATUS_NO_MEMORY
;
status
=
IoCallDriver
(
impl
->
bus_device
,
irp
);
if
(
status
==
STATUS_PENDING
)
KeWaitForSingleObject
(
&
event
,
Executive
,
KernelMode
,
FALSE
,
NULL
);
return
io
.
Status
;
}
static
NTSTATUS
initialize_device
(
DEVICE_OBJECT
*
device
)
{
struct
device
*
impl
=
impl_from_DEVICE_OBJECT
(
device
);
HID_COLLECTION_INFORMATION
info
;
USHORT
usage
,
count
,
report_len
;
HIDP_VALUE_CAPS
value_caps
;
char
*
report_buf
;
NTSTATUS
status
;
HIDP_CAPS
caps
;
if
((
status
=
call_hid_device
(
device
,
IRP_MJ_DEVICE_CONTROL
,
IOCTL_HID_GET_COLLECTION_INFORMATION
,
&
info
,
0
,
&
info
,
sizeof
(
info
)
)))
return
status
;
if
(
!
(
impl
->
preparsed
=
malloc
(
info
.
DescriptorSize
)))
return
STATUS_NO_MEMORY
;
if
((
status
=
call_hid_device
(
device
,
IRP_MJ_DEVICE_CONTROL
,
IOCTL_HID_GET_COLLECTION_DESCRIPTOR
,
NULL
,
0
,
impl
->
preparsed
,
info
.
DescriptorSize
)))
return
status
;
status
=
HidP_GetCaps
(
impl
->
preparsed
,
&
caps
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
return
status
;
count
=
1
;
usage
=
HID_USAGE_DIGITIZER_CONTACT_COUNT_MAX
;
status
=
HidP_GetSpecificValueCaps
(
HidP_Feature
,
HID_USAGE_PAGE_DIGITIZER
,
0
,
usage
,
&
value_caps
,
&
count
,
impl
->
preparsed
);
if
(
status
==
HIDP_STATUS_SUCCESS
)
{
report_len
=
caps
.
FeatureReportByteLength
;
if
(
!
(
report_buf
=
malloc
(
report_len
)))
return
STATUS_NO_MEMORY
;
report_buf
[
0
]
=
value_caps
.
ReportID
;
status
=
call_hid_device
(
device
,
IRP_MJ_DEVICE_CONTROL
,
IOCTL_HID_GET_FEATURE
,
NULL
,
0
,
report_buf
,
report_len
);
if
(
!
status
)
status
=
HidP_GetUsageValue
(
HidP_Feature
,
HID_USAGE_PAGE_DIGITIZER
,
0
,
usage
,
&
impl
->
contact_max
,
impl
->
preparsed
,
report_buf
,
report_len
);
free
(
report_buf
);
if
(
status
&&
status
!=
HIDP_STATUS_SUCCESS
)
return
status
;
count
=
1
;
usage
=
HID_USAGE_DIGITIZER_CONTACT_COUNT
;
status
=
HidP_GetSpecificValueCaps
(
HidP_Input
,
HID_USAGE_PAGE_DIGITIZER
,
0
,
usage
,
&
value_caps
,
&
count
,
impl
->
preparsed
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
goto
failed
;
count
=
caps
.
NumberLinkCollectionNodes
;
usage
=
HID_USAGE_DIGITIZER_CONTACT_ID
;
if
(
!
(
impl
->
id_caps
=
malloc
(
sizeof
(
*
impl
->
id_caps
)
*
caps
.
NumberLinkCollectionNodes
)))
return
STATUS_NO_MEMORY
;
status
=
HidP_GetSpecificValueCaps
(
HidP_Input
,
HID_USAGE_PAGE_DIGITIZER
,
0
,
usage
,
impl
->
id_caps
,
&
count
,
impl
->
preparsed
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
goto
failed
;
impl
->
caps_count
=
count
;
count
=
impl
->
caps_count
;
usage
=
HID_USAGE_GENERIC_X
;
if
(
!
(
impl
->
x_caps
=
malloc
(
sizeof
(
*
impl
->
x_caps
)
*
impl
->
caps_count
)))
return
STATUS_NO_MEMORY
;
status
=
HidP_GetSpecificValueCaps
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
usage
,
impl
->
x_caps
,
&
count
,
impl
->
preparsed
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
goto
failed
;
count
=
impl
->
caps_count
;
usage
=
HID_USAGE_GENERIC_Y
;
if
(
!
(
impl
->
y_caps
=
malloc
(
sizeof
(
*
impl
->
y_caps
)
*
impl
->
caps_count
)))
return
STATUS_NO_MEMORY
;
status
=
HidP_GetSpecificValueCaps
(
HidP_Input
,
HID_USAGE_PAGE_GENERIC
,
0
,
usage
,
impl
->
y_caps
,
&
count
,
impl
->
preparsed
);
if
(
status
!=
HIDP_STATUS_SUCCESS
)
goto
failed
;
return
STATUS_SUCCESS
;
}
failed:
ERR
(
"%#x usage not found, unsupported device
\n
"
,
usage
);
return
STATUS_NOT_SUPPORTED
;
}
static
NTSTATUS
WINAPI
set_event_completion
(
DEVICE_OBJECT
*
device
,
IRP
*
irp
,
void
*
context
)
{
if
(
irp
->
PendingReturned
)
KeSetEvent
(
(
KEVENT
*
)
context
,
IO_NO_INCREMENT
,
FALSE
);
...
...
@@ -98,6 +212,7 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp )
KeWaitForSingleObject
(
&
event
,
Executive
,
KernelMode
,
FALSE
,
NULL
);
status
=
irp
->
IoStatus
.
Status
;
}
if
(
!
status
)
status
=
initialize_device
(
device
);
if
(
status
)
irp
->
IoStatus
.
Status
=
status
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
...
...
@@ -111,6 +226,10 @@ static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp )
IoSkipCurrentIrpStackLocation
(
irp
);
status
=
IoCallDriver
(
impl
->
bus_device
,
irp
);
IoDetachDevice
(
impl
->
bus_device
);
free
(
impl
->
id_caps
);
free
(
impl
->
x_caps
);
free
(
impl
->
y_caps
);
free
(
impl
->
preparsed
);
IoDeleteDevice
(
device
);
return
status
;
...
...
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