Rémi Bernon : dinput: Implement hid_joystick_SendForceFeedbackCommand.
Alexandre Julliard
julliard at winehq.org
Fri Oct 1 18:02:22 CDT 2021
Module: wine
Branch: master
Commit: a382646e38cdc8f7473cd14f9793450bcb701a0f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a382646e38cdc8f7473cd14f9793450bcb701a0f
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Fri Oct 1 09:31:02 2021 +0200
dinput: Implement hid_joystick_SendForceFeedbackCommand.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/dinput/joystick_hid.c | 51 ++++++++++++++++++++++++++++++++++++++--------
dlls/dinput8/tests/hid.c | 18 ++++++++--------
2 files changed, 51 insertions(+), 18 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index b10ce7fc03b..aee8118191f 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -104,6 +104,7 @@ struct hid_joystick
struct extra_caps *input_extra_caps;
char *input_report_buf;
+ char *output_report_buf;
USAGE_AND_PAGE *usages_buf;
ULONG usages_count;
@@ -369,6 +370,7 @@ static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface )
if (!(ref = IDirectInputDevice2WImpl_Release( iface )))
{
HeapFree( GetProcessHeap(), 0, tmp.usages_buf );
+ HeapFree( GetProcessHeap(), 0, tmp.output_report_buf );
HeapFree( GetProcessHeap(), 0, tmp.input_report_buf );
HeapFree( GetProcessHeap(), 0, tmp.input_extra_caps );
HidD_FreePreparsedData( tmp.preparsed );
@@ -833,20 +835,48 @@ static HRESULT WINAPI hid_joystick_GetForceFeedbackState( IDirectInputDevice8W *
static HRESULT WINAPI hid_joystick_SendForceFeedbackCommand( IDirectInputDevice8W *iface, DWORD command )
{
- FIXME( "iface %p, command %x stub!\n", iface, command );
+ struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
+ struct pid_control_report *report = &impl->pid_device_control;
+ ULONG report_len = impl->caps.OutputReportByteLength;
+ char *report_buf = impl->output_report_buf;
+ NTSTATUS status;
+ USAGE usage;
+ ULONG count;
+ HRESULT hr;
+
+ TRACE( "iface %p, flags %x.\n", iface, command );
switch (command)
{
- case DISFFC_RESET:
- case DISFFC_STOPALL:
- case DISFFC_PAUSE:
- case DISFFC_CONTINUE:
- case DISFFC_SETACTUATORSON:
- case DISFFC_SETACTUATORSOFF:
- return DIERR_UNSUPPORTED;
+ case DISFFC_RESET: usage = PID_USAGE_DC_DEVICE_RESET; break;
+ case DISFFC_STOPALL: usage = PID_USAGE_DC_STOP_ALL_EFFECTS; break;
+ case DISFFC_PAUSE: usage = PID_USAGE_DC_DEVICE_PAUSE; break;
+ case DISFFC_CONTINUE: usage = PID_USAGE_DC_DEVICE_CONTINUE; break;
+ case DISFFC_SETACTUATORSON: usage = PID_USAGE_DC_ENABLE_ACTUATORS; break;
+ case DISFFC_SETACTUATORSOFF: usage = PID_USAGE_DC_DISABLE_ACTUATORS; break;
+ default: return DIERR_INVALIDPARAM;
}
- return DIERR_INVALIDPARAM;
+ if (!(impl->dev_caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_UNSUPPORTED;
+
+ EnterCriticalSection( &impl->base.crit );
+ if (!impl->base.acquired || !(impl->base.dwCoopLevel & DISCL_EXCLUSIVE))
+ hr = DIERR_NOTEXCLUSIVEACQUIRED;
+ else
+ {
+ count = 1;
+ status = HidP_InitializeReportForID( HidP_Output, report->id, impl->preparsed, report_buf, report_len );
+ if (status != HIDP_STATUS_SUCCESS) hr = status;
+ else status = HidP_SetUsages( HidP_Output, HID_USAGE_PAGE_PID, report->control_coll, &usage,
+ &count, impl->preparsed, report_buf, report_len );
+
+ if (status != HIDP_STATUS_SUCCESS) hr = status;
+ else if (WriteFile( impl->device, report_buf, report_len, NULL, NULL )) hr = DI_OK;
+ else hr = DIERR_GENERIC;
+ }
+ LeaveCriticalSection( &impl->base.crit );
+
+ return hr;
}
static HRESULT WINAPI hid_joystick_EnumCreatedEffectObjects( IDirectInputDevice8W *iface,
@@ -1555,6 +1585,9 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
size = impl->caps.InputReportByteLength;
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) goto failed;
impl->input_report_buf = buffer;
+ size = impl->caps.OutputReportByteLength;
+ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size ))) goto failed;
+ impl->output_report_buf = buffer;
impl->usages_count = HidP_MaxUsageListLength( HidP_Input, 0, impl->preparsed );
size = impl->usages_count * sizeof(USAGE_AND_PAGE);
if (!(usages = HeapAlloc( GetProcessHeap(), 0, size ))) goto failed;
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 638d8f0aaeb..618fb4e4c7c 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5253,6 +5253,13 @@ static void test_force_feedback_joystick( void )
.dwFFDriverVersion = 1,
};
struct hid_expect expect_dc_reset =
+ {
+ .code = IOCTL_HID_WRITE_REPORT,
+ .report_id = 1,
+ .report_len = 2,
+ .report_buf = {1, 0x01},
+ };
+ struct hid_expect expect_dc_reset_todo =
{
.code = IOCTL_HID_WRITE_REPORT,
.todo = TRUE,
@@ -5751,7 +5758,6 @@ static void test_force_feedback_joystick( void )
todo_wine
ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "IDirectInputDevice8_GetForceFeedbackState returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
- todo_wine
ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
escape.dwSize = sizeof(DIEFFESCAPE);
@@ -5769,7 +5775,7 @@ static void test_force_feedback_joystick( void )
hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
ok( hr == DI_OK, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, &expect_dc_reset_todo, sizeof(expect_dc_reset_todo) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "IDirectInputDevice8_Acquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
@@ -5792,24 +5798,18 @@ static void test_force_feedback_joystick( void )
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
- todo_wine
ok( hr == DI_OK, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
set_hid_expect( file, NULL, 0 );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_STOPALL );
- todo_wine
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_PAUSE );
- todo_wine
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_CONTINUE );
- todo_wine
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSON );
- todo_wine
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSOFF );
- todo_wine
ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
objdata.dwOfs = 0x1e;
@@ -5821,7 +5821,7 @@ static void test_force_feedback_joystick( void )
test_periodic_effect( device, file );
- set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
+ set_hid_expect( file, &expect_dc_reset_todo, sizeof(expect_dc_reset_todo) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
More information about the wine-cvs
mailing list