[PATCH 2/9] dinput8/tests: Add some HID device gain report tests.
Rémi Bernon
rbernon at codeweavers.com
Wed Nov 17 02:19:47 CST 2021
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/joystick_hid.c | 2 +
dlls/dinput8/tests/device.c | 18 +++
dlls/dinput8/tests/driver_hid.c | 83 +++++++++++
dlls/dinput8/tests/driver_hid.h | 3 +-
dlls/dinput8/tests/hid.c | 245 ++++++++++++++++++++++++--------
5 files changed, 290 insertions(+), 61 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 4af7da6654d..57e08025650 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -322,6 +322,8 @@ static const WCHAR *object_usage_to_string( DIDEVICEOBJECTINSTANCEW *instance )
case MAKELONG(PID_USAGE_DC_ENABLE_ACTUATORS, HID_USAGE_PAGE_PID): return L"DC Enable Actuators";
case MAKELONG(PID_USAGE_DC_STOP_ALL_EFFECTS, HID_USAGE_PAGE_PID): return L"DC Stop All Effects";
+ case MAKELONG(PID_USAGE_DEVICE_GAIN, HID_USAGE_PAGE_PID): return L"Device Gain";
+ case MAKELONG(PID_USAGE_DEVICE_GAIN_REPORT, HID_USAGE_PAGE_PID): return L"Device Gain Report";
case MAKELONG(PID_USAGE_CP_OFFSET, HID_USAGE_PAGE_PID): return L"CP Offset";
case MAKELONG(PID_USAGE_DEAD_BAND, HID_USAGE_PAGE_PID): return L"Dead Band";
case MAKELONG(PID_USAGE_DEVICE_CONTROL, HID_USAGE_PAGE_PID): return L"PID Device Control";
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 5ae9e225dc9..019f63ad825 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -1414,6 +1414,15 @@ static void test_mouse_info(void)
ok( prop_range.lMin == DIPROPRANGE_NOMIN, "got %d expected %d\n", prop_range.lMin, DIPROPRANGE_NOMIN );
ok( prop_range.lMax == DIPROPRANGE_NOMAX, "got %d expected %d\n", prop_range.lMax, DIPROPRANGE_NOMAX );
+ prop_range.diph.dwHow = DIPH_DEVICE;
+ prop_range.diph.dwObj = 0;
+ prop_dword.dwData = 0xdeadbeef;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+ prop_dword.dwData = 1000;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+
res = 0;
hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );
@@ -1732,6 +1741,15 @@ static void test_keyboard_info(void)
hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_RANGE returned %#x\n", hr );
+ prop_range.diph.dwHow = DIPH_DEVICE;
+ prop_range.diph.dwObj = 0;
+ prop_dword.dwData = 0xdeadbeef;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+ prop_dword.dwData = 1000;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+
res = 0;
hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );
diff --git a/dlls/dinput8/tests/driver_hid.c b/dlls/dinput8/tests/driver_hid.c
index d6f085e4f30..2201fd07080 100644
--- a/dlls/dinput8/tests/driver_hid.c
+++ b/dlls/dinput8/tests/driver_hid.c
@@ -55,6 +55,7 @@ struct expect_queue
struct hid_expect *end;
struct hid_expect spurious;
struct hid_expect *buffer;
+ IRP *pending_wait;
};
static void expect_queue_init( struct expect_queue *queue )
@@ -68,6 +69,24 @@ static void expect_queue_init( struct expect_queue *queue )
static void expect_queue_cleanup( struct expect_queue *queue )
{
+ KIRQL irql;
+ IRP *irp;
+
+ KeAcquireSpinLock( &queue->lock, &irql );
+ if ((irp = queue->pending_wait))
+ {
+ queue->pending_wait = NULL;
+ if (!IoSetCancelRoutine( irp, NULL )) irp = NULL;
+ }
+ KeReleaseSpinLock( &queue->lock, irql );
+
+ if (irp)
+ {
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_DELETE_PENDING;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+ }
+
ExFreePool( queue->buffer );
}
@@ -112,6 +131,54 @@ static void expect_queue_reset( struct expect_queue *queue, void *buffer, unsign
ExFreePool( missing );
}
+static void WINAPI wait_cancel_routine( DEVICE_OBJECT *device, IRP *irp )
+{
+ struct expect_queue *queue = irp->Tail.Overlay.DriverContext[0];
+ KIRQL irql;
+
+ IoReleaseCancelSpinLock( irp->CancelIrql );
+
+ KeAcquireSpinLock( &queue->lock, &irql );
+ queue->pending_wait = NULL;
+ KeReleaseSpinLock( &queue->lock, irql );
+
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+}
+
+static NTSTATUS expect_queue_wait( struct expect_queue *queue, IRP *irp )
+{
+ NTSTATUS status;
+ KIRQL irql;
+
+ KeAcquireSpinLock( &queue->lock, &irql );
+ if (queue->pos == queue->end)
+ status = STATUS_SUCCESS;
+ else
+ {
+ IoSetCancelRoutine( irp, wait_cancel_routine );
+ if (irp->Cancel && !IoSetCancelRoutine( irp, NULL ))
+ status = STATUS_CANCELLED;
+ else
+ {
+ irp->Tail.Overlay.DriverContext[0] = queue;
+ IoMarkIrpPending( irp );
+ queue->pending_wait = irp;
+ status = STATUS_PENDING;
+ }
+ }
+ KeReleaseSpinLock( &queue->lock, irql );
+
+ if (status == STATUS_SUCCESS)
+ {
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+ }
+
+ return status;
+}
+
static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_PACKET *packet,
LONG *index, struct hid_expect *expect, BOOL compare_buf )
{
@@ -119,6 +186,7 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_
ULONG len = packet->reportBufferLen;
BYTE *buf = packet->reportBuffer;
BYTE id = packet->reportId;
+ IRP *irp = NULL;
KIRQL irql;
missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE );
@@ -140,8 +208,21 @@ static void expect_queue_next( struct expect_queue *queue, ULONG code, HID_XFER_
if (tmp < queue->end) queue->pos = tmp + 1;
else tmp = &queue->spurious;
*expect = *tmp;
+
+ if (queue->pos == queue->end && (irp = queue->pending_wait))
+ {
+ queue->pending_wait = NULL;
+ if (!IoSetCancelRoutine( irp, NULL )) irp = NULL;
+ }
KeReleaseSpinLock( &queue->lock, irql );
+ if (irp)
+ {
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest( irp, IO_NO_INCREMENT );
+ }
+
ok( tmp != &queue->spurious, "got spurious packet\n" );
winetest_push_context( "%s expect[%d]", tmp->context, tmp - queue->buffer );
@@ -624,6 +705,8 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp )
irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
+ case IOCTL_WINETEST_HID_WAIT_EXPECT:
+ return expect_queue_wait( &expect_queue, irp );
case IOCTL_WINETEST_HID_SEND_INPUT:
input_queue_reset( &input_queue, irp->AssociatedIrp.SystemBuffer, in_size );
irp->IoStatus.Status = STATUS_SUCCESS;
diff --git a/dlls/dinput8/tests/driver_hid.h b/dlls/dinput8/tests/driver_hid.h
index 6c355760171..ffd45bd2e35 100644
--- a/dlls/dinput8/tests/driver_hid.h
+++ b/dlls/dinput8/tests/driver_hid.h
@@ -40,7 +40,8 @@
DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3,0x62,0xc0);
#define IOCTL_WINETEST_HID_SET_EXPECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x800, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
-#define IOCTL_WINETEST_HID_SEND_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_HID_WAIT_EXPECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS)
+#define IOCTL_WINETEST_HID_SEND_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x802, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
struct hid_expect
{
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 38bdfb7455e..2534c8afe1f 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -743,7 +743,7 @@ static inline void check_hidp_value_caps_( int line, HIDP_VALUE_CAPS *caps, cons
}
}
-static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, void *out_buf, DWORD *ret_len )
+static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, void *out_buf, DWORD *ret_len, DWORD timeout )
{
OVERLAPPED ovl = {0};
DWORD out_len = ret_len ? *ret_len : 0;
@@ -752,7 +752,19 @@ static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, voi
ovl.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
ret = DeviceIoControl( file, code, in_buf, in_len, out_buf, out_len, &out_len, &ovl );
if (!ret && GetLastError() == ERROR_IO_PENDING)
- ret = GetOverlappedResult( file, &ovl, &out_len, TRUE );
+ {
+ ret = GetOverlappedResultEx( file, &ovl, &out_len, timeout, TRUE );
+ todo_wine_if( timeout != INFINITE )
+ ok( ret, "GetOverlappedResultEx returned %u\n", GetLastError() );
+ }
+ if (!ret && GetLastError() == ERROR_TIMEOUT)
+ {
+ ret = CancelIoEx( file, &ovl );
+ ok( ret, "CancelIoEx returned %u\n", GetLastError() );
+ ret = GetOverlappedResultEx( file, &ovl, &out_len, INFINITE, TRUE );
+ ok( !ret, "GetOverlappedResultEx succeeded\n" );
+ ok( GetLastError() == ERROR_OPERATION_ABORTED, "GetOverlappedResultEx returned %u\n", GetLastError() );
+ }
CloseHandle( ovl.hEvent );
if (ret_len) *ret_len = out_len;
@@ -774,10 +786,20 @@ static void set_hid_expect_( int line, HANDLE file, struct hid_expect *expect, D
for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
- ret = sync_ioctl( file, IOCTL_WINETEST_HID_SET_EXPECT, expect, expect_size, NULL, 0 );
+ ret = sync_ioctl( file, IOCTL_WINETEST_HID_SET_EXPECT, expect, expect_size, NULL, 0, INFINITE );
ok( ret, "IOCTL_WINETEST_HID_SET_EXPECT failed, last error %u\n", GetLastError() );
}
+#define wait_hid_expect( a, b ) wait_hid_expect_( __LINE__, a, b )
+static void wait_hid_expect_( int line, HANDLE file, DWORD timeout )
+{
+ BOOL ret = sync_ioctl( file, IOCTL_WINETEST_HID_WAIT_EXPECT, NULL, 0, NULL, 0, timeout );
+ todo_wine
+ ok( ret, "IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error %u\n", GetLastError() );
+
+ set_hid_expect( file, NULL, 0 );
+}
+
#define send_hid_input( a, b, c ) send_hid_input_( __LINE__, a, b, c )
static void send_hid_input_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size )
{
@@ -793,7 +815,7 @@ static void send_hid_input_( int line, HANDLE file, struct hid_expect *expect, D
for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
- ret = sync_ioctl( file, IOCTL_WINETEST_HID_SEND_INPUT, expect, expect_size, NULL, 0 );
+ ret = sync_ioctl( file, IOCTL_WINETEST_HID_SEND_INPUT, expect, expect_size, NULL, 0, INFINITE );
ok( ret, "IOCTL_WINETEST_HID_SEND_INPUT failed, last error %u\n", GetLastError() );
}
@@ -883,7 +905,7 @@ static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, P
SetLastError( 0xdeadbeef );
length = report_len * 2;
- ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &length );
+ ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &length, INFINITE );
ok( ret, "IOCTL_HID_GET_INPUT_REPORT failed, last error %u\n", GetLastError() );
ok( length == 3, "got length %u, expected 3\n", length );
ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
@@ -977,7 +999,7 @@ static void test_hidp_get_feature( HANDLE file, int report_id, ULONG report_len,
length = report_len * 2;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &length );
+ ret = sync_ioctl( file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &length, INFINITE );
ok( ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError() );
ok( length == 3, "got length %u, expected 3\n", length );
ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
@@ -1073,13 +1095,13 @@ static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len,
length = report_len * 2;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &length );
+ ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &length, INFINITE );
ok( !ret, "IOCTL_HID_SET_FEATURE succeeded\n" );
ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "IOCTL_HID_SET_FEATURE returned error %u\n",
GetLastError() );
length = 0;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, report_len * 2, NULL, &length );
+ ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, report_len * 2, NULL, &length, INFINITE );
ok( ret, "IOCTL_HID_SET_FEATURE failed, last error %u\n", GetLastError() );
ok( length == 3, "got length %u, expected 3\n", length );
@@ -1168,13 +1190,13 @@ static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len,
length = report_len * 2;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &length );
+ ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &length, INFINITE );
ok( !ret, "IOCTL_HID_SET_OUTPUT_REPORT succeeded\n" );
ok( GetLastError() == ERROR_INVALID_USER_BUFFER,
"IOCTL_HID_SET_OUTPUT_REPORT returned error %u\n", GetLastError() );
length = 0;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, report_len * 2, NULL, &length );
+ ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, report_len * 2, NULL, &length, INFINITE );
ok( ret, "IOCTL_HID_SET_OUTPUT_REPORT failed, last error %u\n", GetLastError() );
ok( length == 3, "got length %u, expected 3\n", length );
@@ -2173,7 +2195,7 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
value = 10;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &value, sizeof(ULONG), NULL, NULL );
+ ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &value, sizeof(ULONG), NULL, NULL, INFINITE );
ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
Sleep( 600 );
@@ -2392,7 +2414,7 @@ static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *exp
{
out_len = sizeof(ULONG);
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
todo_wine
@@ -2401,27 +2423,27 @@ static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *exp
out_len = 0;
poll_freq = 500;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
out_len = 0;
poll_freq = 10001;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
out_len = 0;
poll_freq = 0;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
out_len = sizeof(ULONG);
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
ok( poll_freq == 10000, "got poll_freq %u, expected 10000\n", poll_freq );
@@ -2429,13 +2451,13 @@ static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *exp
out_len = 0;
poll_freq = 500;
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
+ ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
out_len = sizeof(ULONG);
SetLastError( 0xdeadbeef );
- ret = sync_ioctl( async_file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
+ ret = sync_ioctl( async_file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
ok( poll_freq == 500, "got poll_freq %u, expected 500\n", poll_freq );
@@ -4358,7 +4380,8 @@ static void test_simple_joystick(void)
ok( hr == DI_OK, "SetEventNotification returned: %#x\n", hr );
file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, 0 );
@@ -5551,12 +5574,30 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
.report_buf = {1,0x01},
},
};
- struct hid_expect expect_dc_reset =
+ struct hid_expect expect_acquire[] =
{
- .code = IOCTL_HID_WRITE_REPORT,
- .report_id = 1,
- .report_len = 2,
- .report_buf = {1, 0x01},
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 1,
+ .report_len = 2,
+ .report_buf = {1, 0x01},
+ },
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 8,
+ .report_len = 2,
+ .report_buf = {8, 0x19},
+ .todo = TRUE,
+ },
+ };
+ struct hid_expect expect_reset[] =
+ {
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 1,
+ .report_len = 2,
+ .report_buf = {1, 0x01},
+ },
};
static const DWORD expect_axes_init[2] = {0};
const DIEFFECT expect_desc_init =
@@ -5689,16 +5730,16 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_reset, sizeof(expect_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
desc.dwDuration = 0xdeadbeef;
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
@@ -5810,16 +5851,16 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
if (version >= 0x700) check_member( desc, expect_desc_init, "%u", dwStartDelay );
else ok( desc.dwStartDelay == 0xcdcdcdcd, "got dwStartDelay %#x\n", desc.dwStartDelay );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_reset, sizeof(expect_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_Download( effect );
ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Download returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
hr = IDirectInputEffect_Download( effect );
ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
@@ -5835,16 +5876,16 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD );
ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_reset, sizeof(expect_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION );
ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION | DIEP_NODOWNLOAD );
ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
@@ -6111,10 +6152,10 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
hr = IDirectInputEffect_Stop( effect );
ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Stop returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
hr = IDirectInputEffect_Unload( effect );
ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
@@ -6291,7 +6332,7 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
winetest_pop_context();
}
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_reset, sizeof(expect_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
@@ -6299,10 +6340,10 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
ref = IDirectInputEffect_Release( effect );
ok( ref == 0, "Release returned %d\n", ref );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
}
static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
@@ -6858,6 +6899,21 @@ static void test_force_feedback_joystick( DWORD version )
REPORT_COUNT(1, 1),
OUTPUT(1, Data|Var|Abs),
END_COLLECTION,
+
+
+ USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT),
+ COLLECTION(1, Logical),
+ REPORT_ID(1, 8),
+
+ USAGE(1, PID_USAGE_DEVICE_GAIN),
+ LOGICAL_MINIMUM(1, 0),
+ LOGICAL_MAXIMUM(2, 0x00ff),
+ PHYSICAL_MINIMUM(1, 0),
+ PHYSICAL_MAXIMUM(2, 0x2710),
+ REPORT_SIZE(1, 8),
+ REPORT_COUNT(1, 1),
+ OUTPUT(1, Data|Var|Abs),
+ END_COLLECTION,
END_COLLECTION,
};
#undef REPORT_ID_OR_USAGE_PAGE
@@ -6881,12 +6937,46 @@ static void test_force_feedback_joystick( DWORD version )
.dwHardwareRevision = 1,
.dwFFDriverVersion = 1,
};
- struct hid_expect expect_dc_reset =
+ struct hid_expect expect_acquire[] =
+ {
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 1,
+ .report_len = 2,
+ .report_buf = {1, 0x01},
+ },
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 8,
+ .report_len = 2,
+ .report_buf = {8, 0x19},
+ .todo = TRUE,
+ },
+ };
+ struct hid_expect expect_reset[] =
+ {
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 1,
+ .report_len = 2,
+ .report_buf = {1, 0x01},
+ },
+ };
+ struct hid_expect expect_set_device_gain_1 =
{
.code = IOCTL_HID_WRITE_REPORT,
- .report_id = 1,
+ .report_id = 8,
.report_len = 2,
- .report_buf = {1, 0x01},
+ .report_buf = {8, 0x19},
+ .todo = TRUE,
+ };
+ struct hid_expect expect_set_device_gain_2 =
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 8,
+ .report_len = 2,
+ .report_buf = {8, 0x33},
+ .todo = TRUE,
};
const DIDEVICEINSTANCEW expect_devinst =
@@ -7004,7 +7094,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Button,
- .dwOfs = version >= 0x800 ? 0x64 : 0x10,
+ .dwOfs = version >= 0x800 ? 0x68 : 0x10,
.dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER,
.dwFlags = DIDOI_FFEFFECTTRIGGER,
.tszName = L"Button 0",
@@ -7016,7 +7106,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Button,
- .dwOfs = version >= 0x800 ? 0x65 : 0x11,
+ .dwOfs = version >= 0x800 ? 0x69 : 0x11,
.dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER,
.dwFlags = DIDOI_FFEFFECTTRIGGER,
.tszName = L"Button 1",
@@ -7028,7 +7118,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x6c : 0,
+ .dwOfs = version >= 0x800 ? 0x70 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(12)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"DC Device Reset",
@@ -7052,7 +7142,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x6d : 0,
+ .dwOfs = version >= 0x800 ? 0x71 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(14)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Op Effect Start",
@@ -7064,7 +7154,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x6e : 0,
+ .dwOfs = version >= 0x800 ? 0x72 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(15)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Op Effect Start Solo",
@@ -7076,7 +7166,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x6f : 0,
+ .dwOfs = version >= 0x800 ? 0x73 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(16)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Op Effect Stop",
@@ -7112,7 +7202,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x70 : 0,
+ .dwOfs = version >= 0x800 ? 0x74 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(19)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"ET Square",
@@ -7124,7 +7214,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x71 : 0,
+ .dwOfs = version >= 0x800 ? 0x75 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(20)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"ET Sine",
@@ -7136,7 +7226,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x72 : 0,
+ .dwOfs = version >= 0x800 ? 0x76 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(21)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"ET Spring",
@@ -7148,7 +7238,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x73 : 0,
+ .dwOfs = version >= 0x800 ? 0x77 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(22)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Z Axis",
@@ -7160,7 +7250,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x74 : 0,
+ .dwOfs = version >= 0x800 ? 0x78 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(23)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Y Axis",
@@ -7172,7 +7262,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x75 : 0,
+ .dwOfs = version >= 0x800 ? 0x79 : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(24)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"X Axis",
@@ -7184,7 +7274,7 @@ static void test_force_feedback_joystick( DWORD version )
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
- .dwOfs = version >= 0x800 ? 0x76 : 0,
+ .dwOfs = version >= 0x800 ? 0x7a : 0,
.dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(25)|DIDFT_OUTPUT,
.dwFlags = 0x80008000,
.tszName = L"Direction Enable",
@@ -7419,6 +7509,18 @@ static void test_force_feedback_joystick( DWORD version )
.wUsage = PID_USAGE_DEAD_BAND,
.wReportId = 7,
},
+ {
+ .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
+ .guidType = GUID_Unknown,
+ .dwOfs = version >= 0x800 ? 0x64 : 0,
+ .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(44)|DIDFT_OUTPUT,
+ .dwFlags = 0x80008000,
+ .tszName = L"Device Gain",
+ .wCollectionNumber = 15,
+ .wUsagePage = HID_USAGE_PAGE_PID,
+ .wUsage = PID_USAGE_DEVICE_GAIN,
+ .wReportId = 8,
+ },
{
.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
.guidType = GUID_Unknown,
@@ -7545,6 +7647,14 @@ static void test_force_feedback_joystick( DWORD version )
.wUsagePage = HID_USAGE_PAGE_PID,
.wUsage = PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET,
},
+ {
+ .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
+ .guidType = GUID_Unknown,
+ .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(15),
+ .tszName = L"Collection 15 - Device Gain Report",
+ .wUsagePage = HID_USAGE_PAGE_PID,
+ .wUsage = PID_USAGE_DEVICE_GAIN_REPORT,
+ },
};
const DIEFFECTINFOW expect_effects[] =
{
@@ -7713,7 +7823,8 @@ static void test_force_feedback_joystick( DWORD version )
ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
@@ -7771,10 +7882,24 @@ static void test_force_feedback_joystick( DWORD version )
hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
+
+ set_hid_expect( file, &expect_set_device_gain_2, sizeof(expect_set_device_gain_2) );
+ prop_dword.dwData = 2000;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ todo_wine
+ ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
+
+ set_hid_expect( file, &expect_set_device_gain_1, sizeof(expect_set_device_gain_1) );
+ prop_dword.dwData = 1000;
+ hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
+ todo_wine
+ ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
hr = IDirectInputDevice8_Escape( device, &escape );
todo_wine
@@ -7792,10 +7917,10 @@ static void test_force_feedback_joystick( DWORD version )
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
ok( hr == DIERR_INVALIDPARAM, "SendForceFeedbackCommand returned %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
ok( hr == DI_OK, "SendForceFeedbackCommand returned %#x\n", hr );
- set_hid_expect( file, NULL, 0 );
+ wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_STOPALL );
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
@@ -7818,7 +7943,7 @@ static void test_force_feedback_joystick( DWORD version )
test_periodic_effect( device, file, version );
test_condition_effect( device, file, version );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, expect_reset, sizeof(expect_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
--
2.33.1
More information about the wine-devel
mailing list