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 );