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
7096c26a
Commit
7096c26a
authored
Aug 03, 2021
by
Rémi Bernon
Committed by
Alexandre Julliard
Aug 04, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
hidclass.sys: Implement button array value caps.
Signed-off-by:
Rémi Bernon
<
rbernon@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
26724c3e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
75 additions
and
15 deletions
+75
-15
hidp.c
dlls/hid/hidp.c
+60
-2
descriptor.c
dlls/hidclass.sys/descriptor.c
+8
-3
ntoskrnl.c
dlls/ntoskrnl.exe/tests/ntoskrnl.c
+6
-10
hid.h
include/wine/hid.h
+1
-0
No files found.
dlls/hid/hidp.c
View file @
7096c26a
...
@@ -286,6 +286,18 @@ static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user )
...
@@ -286,6 +286,18 @@ static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user )
{
{
struct
get_usage_params
*
params
=
user
;
struct
get_usage_params
*
params
=
user
;
ULONG
bit
,
last
;
ULONG
bit
,
last
;
BYTE
index
;
if
(
HID_VALUE_CAPS_IS_ARRAY
(
caps
))
{
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
report_count
*
caps
->
bit_size
-
1
;
bit
<=
last
;
bit
+=
8
)
{
if
(
!
(
index
=
params
->
report_buf
[
bit
/
8
]))
continue
;
if
(
params
->
usages
<
params
->
usages_end
)
*
params
->
usages
=
caps
->
usage_min
+
index
-
caps
->
start_index
;
params
->
usages
++
;
}
return
HIDP_STATUS_SUCCESS
;
}
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
++
bit
)
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
++
bit
)
{
{
...
@@ -423,7 +435,22 @@ struct set_usage_params
...
@@ -423,7 +435,22 @@ struct set_usage_params
static
NTSTATUS
set_usage
(
const
struct
hid_value_caps
*
caps
,
void
*
user
)
static
NTSTATUS
set_usage
(
const
struct
hid_value_caps
*
caps
,
void
*
user
)
{
{
struct
set_usage_params
*
params
=
user
;
struct
set_usage_params
*
params
=
user
;
ULONG
bit
=
caps
->
start_bit
+
params
->
usage
-
caps
->
usage_min
;
ULONG
bit
,
last
;
if
(
HID_VALUE_CAPS_IS_ARRAY
(
caps
))
{
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
report_count
*
caps
->
bit_size
-
1
;
bit
<=
last
;
bit
+=
8
)
{
if
(
params
->
report_buf
[
bit
/
8
])
continue
;
params
->
report_buf
[
bit
/
8
]
=
caps
->
start_index
+
params
->
usage
-
caps
->
usage_min
;
break
;
}
if
(
bit
>
last
)
return
HIDP_STATUS_BUFFER_TOO_SMALL
;
return
HIDP_STATUS_NULL
;
}
bit
=
caps
->
start_bit
+
params
->
usage
-
caps
->
usage_min
;
params
->
report_buf
[
bit
/
8
]
|=
(
1
<<
(
bit
%
8
));
params
->
report_buf
[
bit
/
8
]
|=
(
1
<<
(
bit
%
8
));
return
HIDP_STATUS_NULL
;
return
HIDP_STATUS_NULL
;
}
}
...
@@ -595,6 +622,22 @@ static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *use
...
@@ -595,6 +622,22 @@ static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *use
{
{
struct
get_usage_and_page_params
*
params
=
user
;
struct
get_usage_and_page_params
*
params
=
user
;
ULONG
bit
,
last
;
ULONG
bit
,
last
;
BYTE
index
;
if
(
HID_VALUE_CAPS_IS_ARRAY
(
caps
))
{
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
report_count
*
caps
->
bit_size
-
1
;
bit
<=
last
;
bit
+=
8
)
{
if
(
!
(
index
=
params
->
report_buf
[
bit
/
8
]))
continue
;
if
(
params
->
usages
<
params
->
usages_end
)
{
params
->
usages
->
UsagePage
=
caps
->
usage_page
;
params
->
usages
->
Usage
=
caps
->
usage_min
+
index
-
caps
->
start_index
;
}
params
->
usages
++
;
}
return
HIDP_STATUS_SUCCESS
;
}
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
bit
++
)
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
bit
++
)
{
{
...
@@ -667,9 +710,24 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user )
...
@@ -667,9 +710,24 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user )
HIDP_DATA
*
data
=
params
->
data
,
*
data_end
=
params
->
data_end
;
HIDP_DATA
*
data
=
params
->
data
,
*
data_end
=
params
->
data_end
;
ULONG
bit
,
last
,
bit_count
=
caps
->
bit_size
*
caps
->
report_count
;
ULONG
bit
,
last
,
bit_count
=
caps
->
bit_size
*
caps
->
report_count
;
char
*
report_buf
=
params
->
report_buf
;
char
*
report_buf
=
params
->
report_buf
;
BYTE
index
;
if
(
!
caps
->
bit_size
)
return
HIDP_STATUS_SUCCESS
;
if
(
!
caps
->
bit_size
)
return
HIDP_STATUS_SUCCESS
;
if
(
caps
->
bit_size
==
1
)
if
(
HID_VALUE_CAPS_IS_ARRAY
(
caps
))
{
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
report_count
*
caps
->
bit_size
-
1
;
bit
<=
last
;
bit
+=
8
)
{
if
(
!
(
index
=
report_buf
[
bit
/
8
]))
continue
;
if
(
data
<
data_end
)
{
data
->
DataIndex
=
caps
->
data_index_min
+
index
-
caps
->
start_index
;
data
->
On
=
1
;
}
data
++
;
}
}
else
if
(
HID_VALUE_CAPS_IS_BUTTON
(
caps
))
{
{
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
bit
++
)
for
(
bit
=
caps
->
start_bit
,
last
=
bit
+
caps
->
usage_max
-
caps
->
usage_min
;
bit
<=
last
;
bit
++
)
{
{
...
...
dlls/hidclass.sys/descriptor.c
View file @
7096c26a
...
@@ -460,6 +460,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
...
@@ -460,6 +460,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
USHORT
*
data_idx
=
state
->
data_idx
[
type
];
USHORT
*
data_idx
=
state
->
data_idx
[
type
];
ULONG
*
bit_size
=
&
state
->
bit_size
[
type
][
state
->
items
.
report_id
];
ULONG
*
bit_size
=
&
state
->
bit_size
[
type
][
state
->
items
.
report_id
];
struct
feature
*
feature
;
struct
feature
*
feature
;
BOOL
is_array
;
int
j
;
int
j
;
for
(
j
=
0
;
j
<
state
->
items
.
report_count
;
j
++
)
for
(
j
=
0
;
j
<
state
->
items
.
report_count
;
j
++
)
...
@@ -496,10 +497,14 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
...
@@ -496,10 +497,14 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
}
}
value
=
state
->
values
[
type
]
+
*
value_idx
;
value
=
state
->
values
[
type
]
+
*
value_idx
;
state
->
items
.
report_count
-=
usages_size
-
1
;
state
->
items
.
start_index
=
0
;
if
(
!
(
is_array
=
HID_VALUE_CAPS_IS_ARRAY
(
&
state
->
items
)))
state
->
items
.
report_count
-=
usages_size
-
1
;
else
state
->
items
.
start_bit
-=
state
->
items
.
report_count
*
state
->
items
.
bit_size
;
while
(
usages_size
--
)
while
(
usages_size
--
)
{
{
state
->
items
.
start_bit
-=
state
->
items
.
report_count
*
state
->
items
.
bit_size
;
if
(
!
is_array
)
state
->
items
.
start_bit
-=
state
->
items
.
report_count
*
state
->
items
.
bit_size
;
else
state
->
items
.
start_index
+=
1
;
state
->
items
.
usage_page
=
state
->
usages_page
[
usages_size
];
state
->
items
.
usage_page
=
state
->
usages_page
[
usages_size
];
state
->
items
.
usage_min
=
state
->
usages_min
[
usages_size
];
state
->
items
.
usage_min
=
state
->
usages_min
[
usages_size
];
state
->
items
.
usage_max
=
state
->
usages_max
[
usages_size
];
state
->
items
.
usage_max
=
state
->
usages_max
[
usages_size
];
...
@@ -508,7 +513,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
...
@@ -508,7 +513,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
if
(
state
->
items
.
usage_max
||
state
->
items
.
usage_min
)
*
data_idx
=
state
->
items
.
data_index_max
+
1
;
if
(
state
->
items
.
usage_max
||
state
->
items
.
usage_min
)
*
data_idx
=
state
->
items
.
data_index_max
+
1
;
*
value
++
=
state
->
items
;
*
value
++
=
state
->
items
;
*
value_idx
+=
1
;
*
value_idx
+=
1
;
state
->
items
.
report_count
=
1
;
if
(
!
is_array
)
state
->
items
.
report_count
=
1
;
}
}
state
->
items
.
usage_page
=
usage_page
;
state
->
items
.
usage_page
=
usage_page
;
...
...
dlls/ntoskrnl.exe/tests/ntoskrnl.c
View file @
7096c26a
...
@@ -2229,10 +2229,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
...
@@ -2229,10 +2229,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
memcpy
(
buffer
,
report
,
caps
.
InputReportByteLength
);
memcpy
(
buffer
,
report
,
caps
.
InputReportByteLength
);
status
=
HidP_SetUsages
(
HidP_Input
,
HID_USAGE_PAGE_KEYBOARD
,
0
,
usages
,
&
value
,
preparsed_data
,
status
=
HidP_SetUsages
(
HidP_Input
,
HID_USAGE_PAGE_KEYBOARD
,
0
,
usages
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
report
,
caps
.
InputReportByteLength
);
todo_wine
ok
(
status
==
HIDP_STATUS_BUFFER_TOO_SMALL
,
"HidP_SetUsages returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_BUFFER_TOO_SMALL
,
"HidP_SetUsages returned %#x
\n
"
,
status
);
buffer
[
6
]
=
2
;
buffer
[
6
]
=
2
;
buffer
[
7
]
=
4
;
buffer
[
7
]
=
4
;
todo_wine
ok
(
!
memcmp
(
buffer
,
report
,
caps
.
InputReportByteLength
),
"unexpected report data
\n
"
);
ok
(
!
memcmp
(
buffer
,
report
,
caps
.
InputReportByteLength
),
"unexpected report data
\n
"
);
status
=
HidP_SetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_LED
,
0
,
6
,
1
,
status
=
HidP_SetUsageValue
(
HidP_Input
,
HID_USAGE_PAGE_LED
,
0
,
6
,
1
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
...
@@ -2272,7 +2272,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
...
@@ -2272,7 +2272,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
status
=
HidP_GetUsagesEx
(
HidP_Input
,
0
,
usage_and_pages
,
&
value
,
preparsed_data
,
report
,
status
=
HidP_GetUsagesEx
(
HidP_Input
,
0
,
usage_and_pages
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
caps
.
InputReportByteLength
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetUsagesEx returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetUsagesEx returned %#x
\n
"
,
status
);
todo_wine
ok
(
value
==
6
,
"got usage count %d, expected %d
\n
"
,
value
,
4
);
ok
(
value
==
6
,
"got usage count %d, expected %d
\n
"
,
value
,
4
);
ok
(
usage_and_pages
[
0
].
UsagePage
==
HID_USAGE_PAGE_BUTTON
,
"got usage_and_pages[0] UsagePage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
0
].
UsagePage
==
HID_USAGE_PAGE_BUTTON
,
"got usage_and_pages[0] UsagePage %x, expected %x
\n
"
,
usage_and_pages
[
0
].
UsagePage
,
HID_USAGE_PAGE_BUTTON
);
usage_and_pages
[
0
].
UsagePage
,
HID_USAGE_PAGE_BUTTON
);
ok
(
usage_and_pages
[
1
].
UsagePage
==
HID_USAGE_PAGE_BUTTON
,
"got usage_and_pages[1] UsagePage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
1
].
UsagePage
==
HID_USAGE_PAGE_BUTTON
,
"got usage_and_pages[1] UsagePage %x, expected %x
\n
"
,
...
@@ -2281,7 +2281,6 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
...
@@ -2281,7 +2281,6 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
usage_and_pages
[
2
].
UsagePage
,
HID_USAGE_PAGE_KEYBOARD
);
usage_and_pages
[
2
].
UsagePage
,
HID_USAGE_PAGE_KEYBOARD
);
ok
(
usage_and_pages
[
3
].
UsagePage
==
HID_USAGE_PAGE_KEYBOARD
,
"got usage_and_pages[3] UsagePage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
3
].
UsagePage
==
HID_USAGE_PAGE_KEYBOARD
,
"got usage_and_pages[3] UsagePage %x, expected %x
\n
"
,
usage_and_pages
[
3
].
UsagePage
,
HID_USAGE_PAGE_KEYBOARD
);
usage_and_pages
[
3
].
UsagePage
,
HID_USAGE_PAGE_KEYBOARD
);
todo_wine
ok
(
usage_and_pages
[
4
].
UsagePage
==
HID_USAGE_PAGE_LED
,
"got usage_and_pages[4] UsagePage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
4
].
UsagePage
==
HID_USAGE_PAGE_LED
,
"got usage_and_pages[4] UsagePage %x, expected %x
\n
"
,
usage_and_pages
[
4
].
UsagePage
,
HID_USAGE_PAGE_LED
);
usage_and_pages
[
4
].
UsagePage
,
HID_USAGE_PAGE_LED
);
ok
(
usage_and_pages
[
5
].
UsagePage
==
HID_USAGE_PAGE_LED
,
"got usage_and_pages[5] UsagePage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
5
].
UsagePage
==
HID_USAGE_PAGE_LED
,
"got usage_and_pages[5] UsagePage %x, expected %x
\n
"
,
...
@@ -2292,13 +2291,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
...
@@ -2292,13 +2291,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
usage_and_pages
[
1
].
Usage
,
6
);
usage_and_pages
[
1
].
Usage
,
6
);
ok
(
usage_and_pages
[
2
].
Usage
==
9
,
"got usage_and_pages[2] Usage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
2
].
Usage
==
9
,
"got usage_and_pages[2] Usage %x, expected %x
\n
"
,
usage_and_pages
[
2
].
Usage
,
9
);
usage_and_pages
[
2
].
Usage
,
9
);
todo_wine
ok
(
usage_and_pages
[
3
].
Usage
==
11
,
"got usage_and_pages[3] Usage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
3
].
Usage
==
11
,
"got usage_and_pages[3] Usage %x, expected %x
\n
"
,
usage_and_pages
[
3
].
Usage
,
11
);
usage_and_pages
[
3
].
Usage
,
11
);
todo_wine
ok
(
usage_and_pages
[
4
].
Usage
==
6
,
"got usage_and_pages[4] Usage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
4
].
Usage
==
6
,
"got usage_and_pages[4] Usage %x, expected %x
\n
"
,
usage_and_pages
[
4
].
Usage
,
6
);
usage_and_pages
[
4
].
Usage
,
6
);
todo_wine
ok
(
usage_and_pages
[
5
].
Usage
==
4
,
"got usage_and_pages[5] Usage %x, expected %x
\n
"
,
ok
(
usage_and_pages
[
5
].
Usage
==
4
,
"got usage_and_pages[5] Usage %x, expected %x
\n
"
,
usage_and_pages
[
5
].
Usage
,
4
);
usage_and_pages
[
5
].
Usage
,
4
);
...
@@ -2314,15 +2310,15 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
...
@@ -2314,15 +2310,15 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
value
=
1
;
value
=
1
;
status
=
HidP_GetData
(
HidP_Input
,
data
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
status
=
HidP_GetData
(
HidP_Input
,
data
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
ok
(
status
==
HIDP_STATUS_BUFFER_TOO_SMALL
,
"HidP_GetData returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_BUFFER_TOO_SMALL
,
"HidP_GetData returned %#x
\n
"
,
status
);
todo_wine
ok
(
value
==
11
,
"got data count %d, expected %d
\n
"
,
value
,
11
);
ok
(
value
==
11
,
"got data count %d, expected %d
\n
"
,
value
,
11
);
memset
(
data
,
0
,
sizeof
(
data
));
memset
(
data
,
0
,
sizeof
(
data
));
status
=
HidP_GetData
(
HidP_Input
,
data
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
status
=
HidP_GetData
(
HidP_Input
,
data
,
&
value
,
preparsed_data
,
report
,
caps
.
InputReportByteLength
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetData returned %#x
\n
"
,
status
);
ok
(
status
==
HIDP_STATUS_SUCCESS
,
"HidP_GetData returned %#x
\n
"
,
status
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
expect_data
);
++
i
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
expect_data
);
++
i
)
{
{
winetest_push_context
(
"data[%d]"
,
i
);
winetest_push_context
(
"data[%d]"
,
i
);
todo_wine_if
(
i
>=
4
)
check_member
(
data
[
i
],
expect_data
[
i
],
"%d"
,
DataIndex
);
check_member
(
data
[
i
],
expect_data
[
i
],
"%d"
,
DataIndex
);
todo_wine_if
(
i
>=
4
)
check_member
(
data
[
i
],
expect_data
[
i
],
"%d"
,
RawValue
);
check_member
(
data
[
i
],
expect_data
[
i
],
"%d"
,
RawValue
);
winetest_pop_context
();
winetest_pop_context
();
}
}
...
...
include/wine/hid.h
View file @
7096c26a
...
@@ -60,6 +60,7 @@ struct hid_value_caps
...
@@ -60,6 +60,7 @@ struct hid_value_caps
USHORT
bit_size
;
USHORT
bit_size
;
USHORT
report_count
;
USHORT
report_count
;
ULONG
start_bit
;
ULONG
start_bit
;
ULONG
start_index
;
LONG
logical_min
;
LONG
logical_min
;
LONG
logical_max
;
LONG
logical_max
;
LONG
physical_min
;
LONG
physical_min
;
...
...
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