tangled
alpha
login
or
join now
huwcampbell.com
/
reactos
0
fork
atom
Reactos
0
fork
atom
overview
issues
pulls
pipelines
[HID_WINETEST] Import from Wine Staging 3.3. CORE-14434
Amine Khaldi
8 years ago
845faec4
4049e52e
+409
-2
5 changed files
expand all
collapse all
unified
split
dll
win32
hid
CMakeLists.txt
modules
rostests
winetests
CMakeLists.txt
hid
CMakeLists.txt
device.c
testlist.c
+2
-2
dll/win32/hid/CMakeLists.txt
reviewed
···
1
1
+
2
2
+
spec2def(hid.dll hid.spec ADD_IMPORTLIB)
1
3
2
4
list(APPEND SOURCE
3
5
hid.c
4
6
stubs.c
5
7
precomp.h)
6
6
-
7
7
-
spec2def(hid.dll hid.spec)
8
8
9
9
add_library(hid SHARED
10
10
${SOURCE}
+1
modules/rostests/winetests/CMakeLists.txt
reviewed
···
30
30
add_subdirectory(fusion)
31
31
add_subdirectory(gdi32)
32
32
add_subdirectory(gdiplus)
33
33
+
add_subdirectory(hid)
33
34
add_subdirectory(hlink)
34
35
add_subdirectory(hnetcfg)
35
36
add_subdirectory(imagehlp)
+5
modules/rostests/winetests/hid/CMakeLists.txt
reviewed
···
1
1
+
2
2
+
add_executable(hid_winetest device.c testlist.c)
3
3
+
set_module_type(hid_winetest win32cui)
4
4
+
add_importlibs(hid_winetest hid setupapi msvcrt kernel32)
5
5
+
add_rostests_file(TARGET hid_winetest)
+389
modules/rostests/winetests/hid/device.c
reviewed
···
1
1
+
/*
2
2
+
* Copyright (c) 2017 Aric Stewart
3
3
+
*
4
4
+
* This library is free software; you can redistribute it and/or
5
5
+
* modify it under the terms of the GNU Lesser General Public
6
6
+
* License as published by the Free Software Foundation; either
7
7
+
* version 2.1 of the License, or (at your option) any later version.
8
8
+
*
9
9
+
* This library is distributed in the hope that it will be useful,
10
10
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
11
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
12
+
* Lesser General Public License for more details.
13
13
+
*
14
14
+
* You should have received a copy of the GNU Lesser General Public
15
15
+
* License along with this library; if not, write to the Free Software
16
16
+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
17
+
*/
18
18
+
19
19
+
#include <stdio.h>
20
20
+
#include "ntstatus.h"
21
21
+
#define WIN32_NO_STATUS
22
22
+
#include "windows.h"
23
23
+
#include "setupapi.h"
24
24
+
#include "hidusage.h"
25
25
+
#include "ddk/hidsdi.h"
26
26
+
27
27
+
#include "wine/test.h"
28
28
+
29
29
+
#define READ_MAX_TIME 5000
30
30
+
31
31
+
typedef void (device_test)(HANDLE device);
32
32
+
33
33
+
static void test_device_info(HANDLE device)
34
34
+
{
35
35
+
PHIDP_PREPARSED_DATA ppd;
36
36
+
HIDP_CAPS Caps;
37
37
+
NTSTATUS status;
38
38
+
BOOL rc;
39
39
+
WCHAR device_name[128];
40
40
+
41
41
+
rc = HidD_GetPreparsedData(device, &ppd);
42
42
+
ok(rc, "Failed to get preparsed data(0x%x)\n", GetLastError());
43
43
+
status = HidP_GetCaps(ppd, &Caps);
44
44
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get Caps(0x%x)\n", status);
45
45
+
rc = HidD_GetProductString(device, device_name, sizeof(device_name));
46
46
+
ok(rc, "Failed to get product string(0x%x)\n", GetLastError());
47
47
+
trace("Found device %s (%02x, %02x)\n", wine_dbgstr_w(device_name), Caps.UsagePage, Caps.Usage);
48
48
+
rc = HidD_FreePreparsedData(ppd);
49
49
+
ok(rc, "Failed to free preparsed data(0x%x)\n", GetLastError());
50
50
+
}
51
51
+
52
52
+
static void run_for_each_device(device_test *test)
53
53
+
{
54
54
+
GUID hid_guid;
55
55
+
HDEVINFO info_set;
56
56
+
DWORD index = 0;
57
57
+
SP_DEVICE_INTERFACE_DATA interface_data;
58
58
+
DWORD detail_size = MAX_PATH * sizeof(WCHAR);
59
59
+
SP_DEVICE_INTERFACE_DETAIL_DATA_W *data;
60
60
+
61
61
+
HidD_GetHidGuid(&hid_guid);
62
62
+
63
63
+
ZeroMemory(&interface_data, sizeof(interface_data));
64
64
+
interface_data.cbSize = sizeof(interface_data);
65
65
+
66
66
+
data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) + detail_size);
67
67
+
data->cbSize = sizeof(*data);
68
68
+
69
69
+
info_set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE);
70
70
+
while (SetupDiEnumDeviceInterfaces(info_set, NULL, &hid_guid, index, &interface_data))
71
71
+
{
72
72
+
index ++;
73
73
+
74
74
+
if (SetupDiGetDeviceInterfaceDetailW(info_set, &interface_data, data, sizeof(*data) + detail_size, NULL, NULL))
75
75
+
{
76
76
+
HANDLE file = CreateFileW(data->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
77
77
+
if (file == INVALID_HANDLE_VALUE)
78
78
+
{
79
79
+
trace("Failed to access device %s, likely not plugged in or access is denied.\n", wine_dbgstr_w(data->DevicePath));
80
80
+
continue;
81
81
+
}
82
82
+
83
83
+
test(file);
84
84
+
85
85
+
CloseHandle(file);
86
86
+
}
87
87
+
}
88
88
+
HeapFree(GetProcessHeap(), 0, data);
89
89
+
SetupDiDestroyDeviceInfoList(info_set);
90
90
+
}
91
91
+
92
92
+
static HANDLE get_device(USHORT page, USHORT usages[], UINT usage_count, DWORD access)
93
93
+
{
94
94
+
GUID hid_guid;
95
95
+
HDEVINFO info_set;
96
96
+
DWORD index = 0;
97
97
+
SP_DEVICE_INTERFACE_DATA interface_data;
98
98
+
DWORD detail_size = MAX_PATH * sizeof(WCHAR);
99
99
+
SP_DEVICE_INTERFACE_DETAIL_DATA_W *data;
100
100
+
NTSTATUS status;
101
101
+
BOOL rc;
102
102
+
103
103
+
HidD_GetHidGuid(&hid_guid);
104
104
+
105
105
+
ZeroMemory(&interface_data, sizeof(interface_data));
106
106
+
interface_data.cbSize = sizeof(interface_data);
107
107
+
108
108
+
data = HeapAlloc(GetProcessHeap(), 0 , sizeof(*data) + detail_size);
109
109
+
data->cbSize = sizeof(*data);
110
110
+
111
111
+
info_set = SetupDiGetClassDevsW(&hid_guid, NULL, NULL, DIGCF_DEVICEINTERFACE);
112
112
+
while (SetupDiEnumDeviceInterfaces(info_set, NULL, &hid_guid, index, &interface_data))
113
113
+
{
114
114
+
index ++;
115
115
+
116
116
+
if (SetupDiGetDeviceInterfaceDetailW(info_set, &interface_data, data, sizeof(*data) + detail_size, NULL, NULL))
117
117
+
{
118
118
+
PHIDP_PREPARSED_DATA ppd;
119
119
+
HIDP_CAPS Caps;
120
120
+
HANDLE file = CreateFileW(data->DevicePath, access, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
121
121
+
if (file == INVALID_HANDLE_VALUE)
122
122
+
{
123
123
+
trace("Failed to access device %s, likely not plugged in or access is denied.\n", wine_dbgstr_w(data->DevicePath));
124
124
+
continue;
125
125
+
}
126
126
+
rc = HidD_GetPreparsedData(file, &ppd);
127
127
+
ok(rc, "Failed to get preparsed data(0x%x)\n", GetLastError());
128
128
+
status = HidP_GetCaps(ppd, &Caps);
129
129
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get Caps(0x%x)\n", status);
130
130
+
rc = HidD_FreePreparsedData(ppd);
131
131
+
ok(rc, "Failed to free preparsed data(0x%x)\n", GetLastError());
132
132
+
if (!page || page == Caps.UsagePage)
133
133
+
{
134
134
+
int j;
135
135
+
if (!usage_count)
136
136
+
{
137
137
+
HeapFree(GetProcessHeap(), 0, data);
138
138
+
SetupDiDestroyDeviceInfoList(info_set);
139
139
+
return file;
140
140
+
}
141
141
+
for (j = 0; j < usage_count; j++)
142
142
+
if (!usages[j] || usages[j] == Caps.Usage)
143
143
+
{
144
144
+
HeapFree(GetProcessHeap(), 0, data);
145
145
+
SetupDiDestroyDeviceInfoList(info_set);
146
146
+
return file;
147
147
+
}
148
148
+
}
149
149
+
CloseHandle(file);
150
150
+
}
151
151
+
}
152
152
+
HeapFree(GetProcessHeap(), 0, data);
153
153
+
SetupDiDestroyDeviceInfoList(info_set);
154
154
+
return NULL;
155
155
+
}
156
156
+
157
157
+
static void process_data(HIDP_CAPS Caps, PHIDP_PREPARSED_DATA ppd, CHAR *data, DWORD data_length)
158
158
+
{
159
159
+
INT i;
160
160
+
NTSTATUS status;
161
161
+
162
162
+
if (Caps.NumberInputButtonCaps)
163
163
+
{
164
164
+
USAGE button_pages[100];
165
165
+
166
166
+
for (i = 1; i < 0xff; i++)
167
167
+
{
168
168
+
ULONG usage_length = 100;
169
169
+
status = HidP_GetUsages(HidP_Input, i, 0, button_pages, &usage_length, ppd, data, data_length);
170
170
+
ok (status == HIDP_STATUS_SUCCESS || usage_length == 0,
171
171
+
"HidP_GetUsages failed (%x) but usage length still %i\n", status, usage_length);
172
172
+
if (usage_length)
173
173
+
{
174
174
+
CHAR report[50];
175
175
+
int count;
176
176
+
int j;
177
177
+
178
178
+
count = usage_length;
179
179
+
j = 0;
180
180
+
report[0] = 0;
181
181
+
trace("\tButtons [0x%x: %i buttons]:\n", i, usage_length);
182
182
+
for (count = 0; count < usage_length; count += 15)
183
183
+
{
184
184
+
for (j=count; j < count+15 && j < usage_length; j++)
185
185
+
{
186
186
+
CHAR btn[7];
187
187
+
sprintf(btn, "%i ", button_pages[j]);
188
188
+
strcat(report, btn);
189
189
+
}
190
190
+
trace("\t\t%s\n", report);
191
191
+
}
192
192
+
}
193
193
+
}
194
194
+
}
195
195
+
196
196
+
if (Caps.NumberInputValueCaps)
197
197
+
{
198
198
+
ULONG value;
199
199
+
USHORT length;
200
200
+
HIDP_VALUE_CAPS *values = NULL;
201
201
+
202
202
+
values = HeapAlloc(GetProcessHeap(), 0, sizeof(HIDP_VALUE_CAPS) * Caps.NumberInputValueCaps);
203
203
+
length = Caps.NumberInputValueCaps;
204
204
+
status = HidP_GetValueCaps(HidP_Input, values, &length, ppd);
205
205
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get value caps (%x)\n",status);
206
206
+
207
207
+
trace("\tValues:\n");
208
208
+
for (i = 0; i < length; i++)
209
209
+
{
210
210
+
status = HidP_GetUsageValue(HidP_Input, values[i].UsagePage, 0,
211
211
+
values[i].Range.UsageMin, &value, ppd, data, data_length);
212
212
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get value [%i,%i] (%x)\n",
213
213
+
values[i].UsagePage, values[i].Range.UsageMin, status);
214
214
+
trace("[%02x, %02x]: %u\n",values[i].UsagePage, values[i].Range.UsageMin, value);
215
215
+
}
216
216
+
217
217
+
HeapFree(GetProcessHeap(), 0, values);
218
218
+
}
219
219
+
}
220
220
+
221
221
+
static void test_read_device(void)
222
222
+
{
223
223
+
PHIDP_PREPARSED_DATA ppd;
224
224
+
HIDP_CAPS Caps;
225
225
+
OVERLAPPED overlapped;
226
226
+
WCHAR device_name[128];
227
227
+
CHAR *data = NULL;
228
228
+
DWORD read;
229
229
+
BOOL rc;
230
230
+
NTSTATUS status;
231
231
+
DWORD timeout, tick, spent, max_time;
232
232
+
char *report;
233
233
+
234
234
+
USAGE device_usages[] = {HID_USAGE_GENERIC_JOYSTICK, HID_USAGE_GENERIC_GAMEPAD};
235
235
+
HANDLE device = get_device(HID_USAGE_PAGE_GENERIC, device_usages, 2, GENERIC_READ);
236
236
+
237
237
+
if (!device)
238
238
+
device = get_device(0x0, NULL, 0x0, GENERIC_READ);
239
239
+
240
240
+
if (!device)
241
241
+
{
242
242
+
trace("No device found for reading\n");
243
243
+
return;
244
244
+
}
245
245
+
rc = HidD_GetProductString(device, device_name, sizeof(device_name));
246
246
+
ok(rc, "Failed to get product string(0x%x)\n", GetLastError());
247
247
+
trace("Read tests on device :%s\n",wine_dbgstr_w(device_name));
248
248
+
249
249
+
rc = HidD_GetPreparsedData(device, &ppd);
250
250
+
ok(rc, "Failed to get preparsed data(0x%x)\n", GetLastError());
251
251
+
status = HidP_GetCaps(ppd, &Caps);
252
252
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get Caps(0x%x)\n", status);
253
253
+
data = HeapAlloc(GetProcessHeap(), 0, Caps.InputReportByteLength);
254
254
+
255
255
+
memset(&overlapped, 0, sizeof(overlapped));
256
256
+
overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
257
257
+
if (winetest_interactive)
258
258
+
{
259
259
+
max_time = READ_MAX_TIME;
260
260
+
timeout = 1000;
261
261
+
}
262
262
+
else
263
263
+
max_time = timeout = 100;
264
264
+
if (winetest_interactive)
265
265
+
trace("Test your device for the next %i seconds\n", max_time/1000);
266
266
+
report = HeapAlloc(GetProcessHeap(), 0, 3 * Caps.InputReportByteLength);
267
267
+
tick = GetTickCount();
268
268
+
spent = 0;
269
269
+
do
270
270
+
{
271
271
+
ReadFile(device, data, Caps.InputReportByteLength, NULL, &overlapped);
272
272
+
if (WaitForSingleObject(overlapped.hEvent, timeout) != WAIT_OBJECT_0)
273
273
+
{
274
274
+
ResetEvent(overlapped.hEvent);
275
275
+
spent = GetTickCount() - tick;
276
276
+
trace("REMAINING: %d ms\n", max_time - spent);
277
277
+
continue;
278
278
+
}
279
279
+
ResetEvent(overlapped.hEvent);
280
280
+
spent = GetTickCount() - tick;
281
281
+
GetOverlappedResult(device, &overlapped, &read, FALSE);
282
282
+
if (read)
283
283
+
{
284
284
+
int i;
285
285
+
286
286
+
report[0] = 0;
287
287
+
for (i = 0; i < read && i < Caps.InputReportByteLength; i++)
288
288
+
{
289
289
+
char bytestr[5];
290
290
+
sprintf(bytestr, "%x ", (BYTE)data[i]);
291
291
+
strcat(report, bytestr);
292
292
+
}
293
293
+
trace("Input report (%i): %s\n", read, report);
294
294
+
295
295
+
process_data(Caps, ppd, data, read);
296
296
+
}
297
297
+
trace("REMAINING: %d ms\n", max_time - spent);
298
298
+
} while(spent < max_time);
299
299
+
300
300
+
CloseHandle(overlapped.hEvent);
301
301
+
rc = HidD_FreePreparsedData(ppd);
302
302
+
ok(rc, "Failed to free preparsed data(0x%x)\n", GetLastError());
303
303
+
CloseHandle(device);
304
304
+
HeapFree(GetProcessHeap(), 0, data);
305
305
+
HeapFree(GetProcessHeap(), 0, report);
306
306
+
}
307
307
+
308
308
+
static void test_get_input_report(void)
309
309
+
{
310
310
+
PHIDP_PREPARSED_DATA ppd;
311
311
+
HIDP_CAPS Caps;
312
312
+
WCHAR device_name[128];
313
313
+
CHAR *data = NULL;
314
314
+
DWORD tick, spent, max_time;
315
315
+
char *report;
316
316
+
BOOL rc;
317
317
+
NTSTATUS status;
318
318
+
319
319
+
USAGE device_usages[] = {HID_USAGE_GENERIC_JOYSTICK, HID_USAGE_GENERIC_GAMEPAD};
320
320
+
HANDLE device = get_device(HID_USAGE_PAGE_GENERIC, device_usages, 2, GENERIC_READ);
321
321
+
322
322
+
if (!device)
323
323
+
device = get_device(0x0, NULL, 0x0, GENERIC_READ);
324
324
+
325
325
+
if (!device)
326
326
+
{
327
327
+
trace("No device found for testing\n");
328
328
+
return;
329
329
+
}
330
330
+
rc = HidD_GetProductString(device, device_name, sizeof(device_name));
331
331
+
ok(rc, "Failed to get product string(0x%x)\n", GetLastError());
332
332
+
trace("HidD_GetInputRpeort tests on device :%s\n",wine_dbgstr_w(device_name));
333
333
+
334
334
+
rc = HidD_GetPreparsedData(device, &ppd);
335
335
+
ok(rc, "Failed to get preparsed data(0x%x)\n", GetLastError());
336
336
+
status = HidP_GetCaps(ppd, &Caps);
337
337
+
ok(status == HIDP_STATUS_SUCCESS, "Failed to get Caps(0x%x)\n", status);
338
338
+
data = HeapAlloc(GetProcessHeap(), 0, Caps.InputReportByteLength);
339
339
+
340
340
+
if (winetest_interactive)
341
341
+
max_time = READ_MAX_TIME;
342
342
+
else
343
343
+
max_time = 100;
344
344
+
if (winetest_interactive)
345
345
+
trace("Test your device for the next %i seconds\n", max_time/1000);
346
346
+
report = HeapAlloc(GetProcessHeap(), 0, 3 * Caps.InputReportByteLength);
347
347
+
tick = GetTickCount();
348
348
+
spent = 0;
349
349
+
do
350
350
+
{
351
351
+
int i;
352
352
+
353
353
+
data[0] = 0; /* Just testing report ID 0 for now, That will catch most devices */
354
354
+
rc = HidD_GetInputReport(device, data, Caps.InputReportByteLength);
355
355
+
spent = GetTickCount() - tick;
356
356
+
357
357
+
if (rc)
358
358
+
{
359
359
+
ok(data[0] == 0, "Report ID (0) is not the first byte of the data\n");
360
360
+
report[0] = 0;
361
361
+
for (i = 0; i < Caps.InputReportByteLength; i++)
362
362
+
{
363
363
+
char bytestr[5];
364
364
+
sprintf(bytestr, "%x ", (BYTE)data[i]);
365
365
+
strcat(report, bytestr);
366
366
+
}
367
367
+
trace("Input report (%i): %s\n", Caps.InputReportByteLength, report);
368
368
+
369
369
+
process_data(Caps, ppd, data, Caps.InputReportByteLength);
370
370
+
}
371
371
+
else
372
372
+
trace("Failed to get Input Report, (%x)\n", rc);
373
373
+
trace("REMAINING: %d ms\n", max_time - spent);
374
374
+
Sleep(500);
375
375
+
} while(spent < max_time);
376
376
+
377
377
+
rc = HidD_FreePreparsedData(ppd);
378
378
+
ok(rc, "Failed to free preparsed data(0x%x)\n", GetLastError());
379
379
+
CloseHandle(device);
380
380
+
HeapFree(GetProcessHeap(), 0, data);
381
381
+
HeapFree(GetProcessHeap(), 0, report);
382
382
+
}
383
383
+
384
384
+
START_TEST(device)
385
385
+
{
386
386
+
run_for_each_device(test_device_info);
387
387
+
test_read_device();
388
388
+
test_get_input_report();
389
389
+
}
+12
modules/rostests/winetests/hid/testlist.c
reviewed
···
1
1
+
/* Automatically generated file; DO NOT EDIT!! */
2
2
+
3
3
+
#define STANDALONE
4
4
+
#include <wine/test.h>
5
5
+
6
6
+
extern void func_device(void);
7
7
+
8
8
+
const struct test winetest_testlist[] =
9
9
+
{
10
10
+
{ "device", func_device },
11
11
+
{ 0, 0 }
12
12
+
};