Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
October 2021
- 81 participants
- 2597 messages
[PATCH 09/10] winebus.sys: Implement PID device control for SDL devices.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winebus.sys/bus_sdl.c | 48 +++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index bd06717165d..772ee092c83 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -47,10 +47,11 @@
#include "ddk/wdm.h"
#include "ddk/hidtypes.h"
#include "ddk/hidsdi.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
#include "hidusage.h"
+#include "wine/debug.h"
+#include "wine/hid.h"
+
#include "unix_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
@@ -95,12 +96,15 @@ MAKE_FUNCPTR(SDL_HapticClose);
MAKE_FUNCPTR(SDL_HapticDestroyEffect);
MAKE_FUNCPTR(SDL_HapticNewEffect);
MAKE_FUNCPTR(SDL_HapticOpenFromJoystick);
+MAKE_FUNCPTR(SDL_HapticPause);
MAKE_FUNCPTR(SDL_HapticQuery);
MAKE_FUNCPTR(SDL_HapticRumbleInit);
MAKE_FUNCPTR(SDL_HapticRumblePlay);
MAKE_FUNCPTR(SDL_HapticRumbleSupported);
MAKE_FUNCPTR(SDL_HapticRunEffect);
+MAKE_FUNCPTR(SDL_HapticSetGain);
MAKE_FUNCPTR(SDL_HapticStopAll);
+MAKE_FUNCPTR(SDL_HapticUnpause);
MAKE_FUNCPTR(SDL_JoystickIsHaptic);
MAKE_FUNCPTR(SDL_GameControllerAddMapping);
MAKE_FUNCPTR(SDL_RegisterEvents);
@@ -130,6 +134,7 @@ struct sdl_device
DWORD effect_support;
SDL_Haptic *sdl_haptic;
int haptic_effect_id;
+ int effect_ids[256];
};
static inline struct sdl_device *impl_from_unix_device(struct unix_device *iface)
@@ -168,6 +173,8 @@ static void set_hat_value(struct unix_device *iface, int index, int value)
static BOOL descriptor_add_haptic(struct sdl_device *impl)
{
+ USHORT i;
+
if (!pSDL_JoystickIsHaptic(impl->sdl_joystick) ||
!(impl->sdl_haptic = pSDL_HapticOpenFromJoystick(impl->sdl_joystick)))
impl->effect_support = 0;
@@ -197,6 +204,7 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
}
impl->haptic_effect_id = -1;
+ for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i) impl->effect_ids[i] = -1;
return TRUE;
}
@@ -400,7 +408,38 @@ NTSTATUS sdl_device_haptics_start(struct unix_device *iface, DWORD duration_ms,
static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, USAGE control)
{
- FIXME("iface %p, control %#04x stub\n", iface, control);
+ struct sdl_device *impl = impl_from_unix_device(iface);
+ unsigned int i;
+
+ TRACE("iface %p, control %#04x.\n", iface, control);
+
+ switch (control)
+ {
+ case PID_USAGE_DC_ENABLE_ACTUATORS:
+ pSDL_HapticSetGain(impl->sdl_haptic, 100);
+ return STATUS_SUCCESS;
+ case PID_USAGE_DC_DISABLE_ACTUATORS:
+ pSDL_HapticSetGain(impl->sdl_haptic, 0);
+ return STATUS_SUCCESS;
+ case PID_USAGE_DC_STOP_ALL_EFFECTS:
+ pSDL_HapticStopAll(impl->sdl_haptic);
+ return STATUS_SUCCESS;
+ case PID_USAGE_DC_DEVICE_RESET:
+ pSDL_HapticStopAll(impl->sdl_haptic);
+ for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i)
+ {
+ if (impl->effect_ids[i] < 0) continue;
+ pSDL_HapticDestroyEffect(impl->sdl_haptic, impl->effect_ids[i]);
+ impl->effect_ids[i] = -1;
+ }
+ return STATUS_SUCCESS;
+ case PID_USAGE_DC_DEVICE_PAUSE:
+ pSDL_HapticPause(impl->sdl_haptic);
+ return STATUS_SUCCESS;
+ case PID_USAGE_DC_DEVICE_CONTINUE:
+ pSDL_HapticUnpause(impl->sdl_haptic);
+ return STATUS_SUCCESS;
+ }
return STATUS_NOT_SUPPORTED;
}
@@ -665,12 +704,15 @@ NTSTATUS sdl_bus_init(void *args)
LOAD_FUNCPTR(SDL_HapticDestroyEffect);
LOAD_FUNCPTR(SDL_HapticNewEffect);
LOAD_FUNCPTR(SDL_HapticOpenFromJoystick);
+ LOAD_FUNCPTR(SDL_HapticPause);
LOAD_FUNCPTR(SDL_HapticQuery);
LOAD_FUNCPTR(SDL_HapticRumbleInit);
LOAD_FUNCPTR(SDL_HapticRumblePlay);
LOAD_FUNCPTR(SDL_HapticRumbleSupported);
LOAD_FUNCPTR(SDL_HapticRunEffect);
+ LOAD_FUNCPTR(SDL_HapticSetGain);
LOAD_FUNCPTR(SDL_HapticStopAll);
+ LOAD_FUNCPTR(SDL_HapticUnpause);
LOAD_FUNCPTR(SDL_JoystickIsHaptic);
LOAD_FUNCPTR(SDL_GameControllerAddMapping);
LOAD_FUNCPTR(SDL_RegisterEvents);
--
2.33.0
Oct. 1, 2021
[PATCH 08/10] dinput: Implement HID joystick IDirectInputDevice8_CreateEffect stub.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 169 ++++++++++++++++++++++++++++++++++++-
dlls/dinput8/tests/hid.c | 3 +-
2 files changed, 169 insertions(+), 3 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index a43ecde0e9c..8f5dbee9dc3 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -120,6 +120,17 @@ static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputD
struct hid_joystick, base );
}
+struct hid_joystick_effect
+{
+ IDirectInputEffect IDirectInputEffect_iface;
+ LONG ref;
+};
+
+static inline struct hid_joystick_effect *impl_from_IDirectInputEffect( IDirectInputEffect *iface )
+{
+ return CONTAINING_RECORD( iface, struct hid_joystick_effect, IDirectInputEffect_iface );
+}
+
static const GUID *object_usage_to_guid( USAGE usage_page, USAGE usage )
{
switch (usage_page)
@@ -803,16 +814,39 @@ static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, D
return S_OK;
}
+static HRESULT hid_joystick_effect_create( IDirectInputEffect **out );
+
static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, const GUID *guid,
const DIEFFECT *params, IDirectInputEffect **out,
IUnknown *outer )
{
- FIXME( "iface %p, guid %s, params %p, out %p, outer %p stub!\n", iface, debugstr_guid( guid ),
+ struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
+ DWORD flags = DIEP_ALLPARAMS;
+ HRESULT hr;
+
+ TRACE( "iface %p, guid %s, params %p, out %p, outer %p\n", iface, debugstr_guid( guid ),
params, out, outer );
if (!out) return E_POINTER;
+ *out = NULL;
- return DIERR_UNSUPPORTED;
+ if (!(impl->dev_caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_UNSUPPORTED;
+ if (FAILED(hr = hid_joystick_effect_create( out ))) return hr;
+
+ hr = IDirectInputEffect_Initialize( *out, DINPUT_instance, impl->base.dinput->dwVersion, guid );
+ if (FAILED(hr)) goto failed;
+
+ if (!params) return DI_OK;
+ if (!impl->base.acquired || !(impl->base.dwCoopLevel & DISCL_EXCLUSIVE))
+ flags |= DIEP_NODOWNLOAD;
+ hr = IDirectInputEffect_SetParameters( *out, params, flags );
+ if (FAILED(hr)) goto failed;
+ return hr;
+
+failed:
+ IDirectInputEffect_Release( *out );
+ *out = NULL;
+ return hr;
}
static HRESULT WINAPI hid_joystick_EnumEffects( IDirectInputDevice8W *iface, LPDIENUMEFFECTSCALLBACKW callback,
@@ -1721,3 +1755,134 @@ const struct dinput_device joystick_hid_device =
hid_joystick_enum_device,
hid_joystick_create_device,
};
+
+static HRESULT WINAPI hid_joystick_effect_QueryInterface( IDirectInputEffect *iface, REFIID iid, void **out )
+{
+ TRACE( "iface %p, iid %s, out %p\n", iface, debugstr_guid( iid ), out );
+
+ if (IsEqualGUID( iid, &IID_IUnknown ) ||
+ IsEqualGUID( iid, &IID_IDirectInputEffect ))
+ {
+ IDirectInputEffect_AddRef( iface );
+ *out = iface;
+ return S_OK;
+ }
+
+ FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI hid_joystick_effect_AddRef( IDirectInputEffect *iface )
+{
+ struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
+ ULONG ref = InterlockedIncrement( &impl->ref );
+ TRACE( "iface %p, ref %u.\n", iface, ref );
+ return ref;
+}
+
+static ULONG WINAPI hid_joystick_effect_Release( IDirectInputEffect *iface )
+{
+ struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
+ ULONG ref = InterlockedDecrement( &impl->ref );
+ TRACE( "iface %p, ref %u.\n", iface, ref );
+ if (!ref) HeapFree( GetProcessHeap(), 0, impl );
+ return ref;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Initialize( IDirectInputEffect *iface, HINSTANCE inst,
+ DWORD version, REFGUID guid )
+{
+ FIXME( "iface %p, inst %p, version %u, guid %s stub!\n", iface, inst, version, debugstr_guid( guid ) );
+ return DI_OK;
+}
+
+static HRESULT WINAPI hid_joystick_effect_GetEffectGuid( IDirectInputEffect *iface, GUID *guid )
+{
+ FIXME( "iface %p, guid %p stub!\n", iface, guid );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags )
+{
+ FIXME( "iface %p, params %p, flags %#x stub!\n", iface, params, flags );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *iface,
+ const DIEFFECT *params, DWORD flags )
+{
+ FIXME( "iface %p, params %p, flags %#x stub!\n", iface, params, flags );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Start( IDirectInputEffect *iface, DWORD iterations, DWORD flags )
+{
+ FIXME( "iface %p, iterations %u, flags %#x stub!\n", iface, iterations, flags );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Stop( IDirectInputEffect *iface )
+{
+ FIXME( "iface %p stub!\n", iface );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_GetEffectStatus( IDirectInputEffect *iface, DWORD *status )
+{
+ FIXME( "iface %p, status %p stub!\n", iface, status );
+
+ if (!status) return E_POINTER;
+
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface )
+{
+ FIXME( "iface %p stub!\n", iface );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Unload( IDirectInputEffect *iface )
+{
+ FIXME( "iface %p stub!\n", iface );
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_effect_Escape( IDirectInputEffect *iface, DIEFFESCAPE *escape )
+{
+ FIXME( "iface %p, escape %p stub!\n", iface, escape );
+ return DIERR_UNSUPPORTED;
+}
+
+static IDirectInputEffectVtbl hid_joystick_effect_vtbl =
+{
+ /*** IUnknown methods ***/
+ hid_joystick_effect_QueryInterface,
+ hid_joystick_effect_AddRef,
+ hid_joystick_effect_Release,
+ /*** IDirectInputEffect methods ***/
+ hid_joystick_effect_Initialize,
+ hid_joystick_effect_GetEffectGuid,
+ hid_joystick_effect_GetParameters,
+ hid_joystick_effect_SetParameters,
+ hid_joystick_effect_Start,
+ hid_joystick_effect_Stop,
+ hid_joystick_effect_GetEffectStatus,
+ hid_joystick_effect_Download,
+ hid_joystick_effect_Unload,
+ hid_joystick_effect_Escape,
+};
+
+static HRESULT hid_joystick_effect_create( IDirectInputEffect **out )
+{
+ struct hid_joystick_effect *impl;
+
+ if (!(impl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*impl) )))
+ return DIERR_OUTOFMEMORY;
+ impl->IDirectInputEffect_iface.lpVtbl = &hid_joystick_effect_vtbl;
+ impl->ref = 1;
+
+ *out = &impl->IDirectInputEffect_iface;
+ return DI_OK;
+}
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 7c46f19cc40..e83cc8a3f7b 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5066,12 +5066,13 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file )
hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL );
todo_wine
ok( hr == E_POINTER, "IDirectInputDevice8_CreateEffect returned %#x\n", hr );
+ if (hr == DI_OK) IDirectInputEffect_Release( effect );
hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL );
todo_wine
ok( hr == DIERR_DEVICENOTREG, "IDirectInputDevice8_CreateEffect returned %#x\n", hr );
+ if (hr == DI_OK) IDirectInputEffect_Release( effect );
hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
- todo_wine
ok( hr == DI_OK, "IDirectInputDevice8_CreateEffect returned %#x\n", hr );
if (hr != DI_OK) return;
--
2.33.0
Oct. 1, 2021
[PATCH 07/10] dinput: Implement HID joystick IDirectInputDevice8_EnumEffects.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 63 +++++++++++++++++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index ac67625cddc..a43ecde0e9c 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -818,10 +818,71 @@ static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, co
static HRESULT WINAPI hid_joystick_EnumEffects( IDirectInputDevice8W *iface, LPDIENUMEFFECTSCALLBACKW callback,
void *context, DWORD type )
{
- FIXME( "iface %p, callback %p, context %p, type %#x stub!\n", iface, callback, context, type );
+ DIEFFECTINFOW info = {.dwSize = sizeof(info)};
+ HRESULT hr;
+
+ TRACE( "iface %p, callback %p, context %p, type %#x.\n", iface, callback, context, type );
if (!callback) return DIERR_INVALIDPARAM;
+ type = DIEFT_GETTYPE( type );
+
+ if (type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
+ {
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_ConstantForce );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+ }
+
+ if (type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
+ {
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_RampForce );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+ }
+
+ if (type == DIEFT_ALL || type == DIEFT_PERIODIC)
+ {
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Square );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Sine );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Triangle );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_SawtoothUp );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_SawtoothDown );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+ }
+
+ if (type == DIEFT_ALL || type == DIEFT_CONDITION)
+ {
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Spring );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Damper );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Inertia );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+
+ hr = IDirectInputDevice8_GetEffectInfo( iface, &info, &GUID_Friction );
+ if (FAILED(hr) && hr != DIERR_DEVICENOTREG) return hr;
+ if (hr == DI_OK && callback( &info, context ) == DIENUM_STOP) return DI_OK;
+ }
+
return DI_OK;
}
--
2.33.0
Oct. 1, 2021
[PATCH 06/10] dinput: Send DISFFC_RESET command on HID joystick (Un)Acquire.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 4 ++++
dlls/dinput8/tests/hid.c | 12 ++----------
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index b6c4c960521..ac67625cddc 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -707,6 +707,8 @@ static HRESULT WINAPI hid_joystick_Acquire( IDirectInputDevice8W *iface )
impl->read_ovl.hEvent = impl->base.read_event;
if (ReadFile( impl->device, impl->input_report_buf, report_len, NULL, &impl->read_ovl ))
impl->base.read_callback( iface );
+
+ IDirectInputDevice8_SendForceFeedbackCommand( iface, DISFFC_RESET );
}
LeaveCriticalSection( &impl->base.crit );
@@ -726,6 +728,8 @@ static HRESULT WINAPI hid_joystick_Unacquire( IDirectInputDevice8W *iface )
{
ret = CancelIoEx( impl->device, &impl->read_ovl );
if (!ret) WARN( "CancelIoEx failed, last error %u\n", GetLastError() );
+
+ IDirectInputDevice8_SendForceFeedbackCommand( iface, DISFFC_RESET );
}
hr = IDirectInputDevice2WImpl_Unacquire( iface );
LeaveCriticalSection( &impl->base.crit );
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 618fb4e4c7c..7c46f19cc40 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5259,14 +5259,6 @@ static void test_force_feedback_joystick( void )
.report_len = 2,
.report_buf = {1, 0x01},
};
- struct hid_expect expect_dc_reset_todo =
- {
- .code = IOCTL_HID_WRITE_REPORT,
- .todo = TRUE,
- .report_id = 1,
- .report_len = 2,
- .report_buf = {1, 0x01},
- };
const DIDEVICEINSTANCEW expect_devinst =
{
@@ -5775,7 +5767,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_todo, sizeof(expect_dc_reset_todo) );
+ set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
hr = IDirectInputDevice8_Acquire( device );
ok( hr == DI_OK, "IDirectInputDevice8_Acquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
@@ -5821,7 +5813,7 @@ static void test_force_feedback_joystick( void )
test_periodic_effect( device, file );
- set_hid_expect( file, &expect_dc_reset_todo, sizeof(expect_dc_reset_todo) );
+ set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
hr = IDirectInputDevice8_Unacquire( device );
ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
set_hid_expect( file, NULL, 0 );
--
2.33.0
Oct. 1, 2021
[PATCH 05/10] dinput: Start and cancel reading HID reports while holding the CS.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index aee8118191f..b6c4c960521 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -699,14 +699,18 @@ static HRESULT WINAPI hid_joystick_Acquire( IDirectInputDevice8W *iface )
TRACE( "iface %p.\n", iface );
- if ((hr = IDirectInputDevice2WImpl_Acquire( iface )) != DI_OK) return hr;
-
- memset( &impl->read_ovl, 0, sizeof(impl->read_ovl) );
- impl->read_ovl.hEvent = impl->base.read_event;
- if (ReadFile( impl->device, impl->input_report_buf, report_len, NULL, &impl->read_ovl ))
- impl->base.read_callback( iface );
+ EnterCriticalSection( &impl->base.crit );
+ hr = IDirectInputDevice2WImpl_Acquire( iface );
+ if (hr == DI_OK)
+ {
+ memset( &impl->read_ovl, 0, sizeof(impl->read_ovl) );
+ impl->read_ovl.hEvent = impl->base.read_event;
+ if (ReadFile( impl->device, impl->input_report_buf, report_len, NULL, &impl->read_ovl ))
+ impl->base.read_callback( iface );
+ }
+ LeaveCriticalSection( &impl->base.crit );
- return DI_OK;
+ return hr;
}
static HRESULT WINAPI hid_joystick_Unacquire( IDirectInputDevice8W *iface )
@@ -717,12 +721,16 @@ static HRESULT WINAPI hid_joystick_Unacquire( IDirectInputDevice8W *iface )
TRACE( "iface %p.\n", iface );
- if ((hr = IDirectInputDevice2WImpl_Unacquire( iface )) != DI_OK) return hr;
-
- ret = CancelIoEx( impl->device, &impl->read_ovl );
- if (!ret) WARN( "CancelIoEx failed, last error %u\n", GetLastError() );
+ EnterCriticalSection( &impl->base.crit );
+ if (impl->base.acquired)
+ {
+ ret = CancelIoEx( impl->device, &impl->read_ovl );
+ if (!ret) WARN( "CancelIoEx failed, last error %u\n", GetLastError() );
+ }
+ hr = IDirectInputDevice2WImpl_Unacquire( iface );
+ LeaveCriticalSection( &impl->base.crit );
- return DI_OK;
+ return hr;
}
static HRESULT WINAPI hid_joystick_GetDeviceState( IDirectInputDevice8W *iface, DWORD len, void *ptr )
--
2.33.0
Oct. 1, 2021
[PATCH 04/10] dinput: Implement hid_joystick_SendForceFeedbackCommand.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
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 );
--
2.33.0
Oct. 1, 2021
[PATCH 03/10] dinput: Look for the PID device control output report.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 90 ++++++++++++++++++++++++++++++++++++++
dlls/dinput8/tests/hid.c | 6 ---
2 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index a6c6de3a889..b10ce7fc03b 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -78,6 +78,13 @@ struct extra_caps
LONG saturation;
};
+struct pid_control_report
+{
+ BYTE id;
+ ULONG collection;
+ ULONG control_coll;
+};
+
#define DEVICE_STATE_MAX_SIZE 1024
struct hid_joystick
@@ -102,6 +109,8 @@ struct hid_joystick
BYTE device_state_report_id;
BYTE device_state[DEVICE_STATE_MAX_SIZE];
+
+ struct pid_control_report pid_device_control;
};
static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface )
@@ -1176,6 +1185,12 @@ static BOOL hid_joystick_device_try_open( UINT32 handle, const WCHAR *path, HAND
instance->wUsagePage = caps->UsagePage;
instance->wUsage = caps->Usage;
+ count = ARRAY_SIZE(buttons);
+ status = HidP_GetSpecificButtonCaps( HidP_Output, HID_USAGE_PAGE_PID, 0,
+ PID_USAGE_DC_DEVICE_RESET, buttons, &count, preparsed_data );
+ if (status == HIDP_STATUS_SUCCESS && count > 0)
+ instance->guidFFDriver = IID_IDirectInputPIDDriver;
+
count = ARRAY_SIZE(buttons);
status = HidP_GetSpecificButtonCaps( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, 0, buttons, &count, preparsed_data );
if (status != HIDP_STATUS_SUCCESS) count = button_count = 0;
@@ -1398,6 +1413,67 @@ static BOOL init_data_format( struct hid_joystick *impl, struct hid_value_caps *
return DIENUM_CONTINUE;
}
+static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps *caps,
+ DIDEVICEOBJECTINSTANCEW *instance, void *data )
+{
+ struct pid_control_report *device_control = &impl->pid_device_control;
+
+#define SET_COLLECTION( rep ) \
+ do \
+ { \
+ if (rep->collection) FIXME( "duplicate " #rep " report!\n" ); \
+ else rep->collection = DIDFT_GETINSTANCE( instance->dwType ); \
+ } while (0)
+
+#define SET_SUB_COLLECTION( rep, sub ) \
+ do { \
+ if (instance->wCollectionNumber != rep->collection) \
+ FIXME( "unexpected " #rep "." #sub " parent!\n" ); \
+ else if (rep->sub) \
+ FIXME( "duplicate " #rep "." #sub " collection!\n" ); \
+ else \
+ rep->sub = DIDFT_GETINSTANCE( instance->dwType ); \
+ } while (0)
+
+ if (instance->wUsagePage == HID_USAGE_PAGE_PID)
+ {
+ switch (instance->wUsage)
+ {
+ case PID_USAGE_DEVICE_CONTROL_REPORT: SET_COLLECTION( device_control ); break;
+ case PID_USAGE_DEVICE_CONTROL: SET_SUB_COLLECTION( device_control, control_coll ); break;
+ }
+ }
+
+#undef SET_SUB_COLLECTION
+#undef SET_COLLECTION
+
+ return DIENUM_CONTINUE;
+}
+
+static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *caps,
+ DIDEVICEOBJECTINSTANCEW *instance, void *data )
+{
+ struct pid_control_report *device_control = &impl->pid_device_control;
+
+ if (!(instance->dwType & DIDFT_OUTPUT)) return DIENUM_CONTINUE;
+
+#define SET_REPORT_ID( rep ) \
+ do \
+ { \
+ if (!rep->id) \
+ rep->id = instance->wReportId; \
+ else if (rep->id != instance->wReportId) \
+ FIXME( "multiple " #rep " report ids!\n" ); \
+ } while (0)
+
+ if (instance->wCollectionNumber == device_control->control_coll)
+ SET_REPORT_ID( device_control );
+
+#undef SET_REPORT_ID
+
+ return DIENUM_CONTINUE;
+}
+
static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID *guid, IDirectInputDevice8W **out )
{
static const DIPROPHEADER filter =
@@ -1485,6 +1561,20 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID
impl->usages_buf = usages;
enum_objects( impl, &filter, DIDFT_ALL, init_objects, NULL );
+ enum_objects( impl, &filter, DIDFT_COLLECTION, init_pid_reports, NULL );
+ enum_objects( impl, &filter, DIDFT_NODATA, init_pid_caps, NULL );
+
+ TRACE( "device control id %u, coll %u, control coll %u\n", impl->pid_device_control.id,
+ impl->pid_device_control.collection, impl->pid_device_control.control_coll );
+
+ if (impl->pid_device_control.id)
+ {
+ impl->dev_caps.dwFlags |= DIDC_FORCEFEEDBACK;
+ impl->dev_caps.dwFFSamplePeriod = 1000000;
+ impl->dev_caps.dwFFMinTimeResolution = 1000000;
+ impl->dev_caps.dwHardwareRevision = 1;
+ impl->dev_caps.dwFFDriverVersion = 1;
+ }
format = impl->base.data_format.wine_df;
if (format->dwDataSize > DEVICE_STATE_MAX_SIZE)
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index e6439ed8fe5..638d8f0aaeb 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -5646,7 +5646,6 @@ static void test_force_feedback_joystick( void )
check_member_wstr( devinst, expect_devinst, tszInstanceName );
todo_wine
check_member_wstr( devinst, expect_devinst, tszProductName );
- todo_wine
check_member_guid( devinst, expect_devinst, guidFFDriver );
check_member( devinst, expect_devinst, "%04x", wUsagePage );
check_member( devinst, expect_devinst, "%04x", wUsage );
@@ -5655,20 +5654,15 @@ static void test_force_feedback_joystick( void )
hr = IDirectInputDevice8_GetCapabilities( device, &caps );
ok( hr == DI_OK, "IDirectInputDevice8_GetCapabilities returned %#x\n", hr );
check_member( caps, expect_caps, "%d", dwSize );
- todo_wine
check_member( caps, expect_caps, "%#x", dwFlags );
check_member( caps, expect_caps, "%#x", dwDevType );
check_member( caps, expect_caps, "%d", dwAxes );
check_member( caps, expect_caps, "%d", dwButtons );
check_member( caps, expect_caps, "%d", dwPOVs );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFSamplePeriod );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFMinTimeResolution );
check_member( caps, expect_caps, "%d", dwFirmwareRevision );
- todo_wine
check_member( caps, expect_caps, "%d", dwHardwareRevision );
- todo_wine
check_member( caps, expect_caps, "%d", dwFFDriverVersion );
prop_dword.dwData = 0xdeadbeef;
--
2.33.0
Oct. 1, 2021
[PATCH 02/10] winebus.sys: Add a PID device control output report.
by Rémi Bernon
And include it in the HID report descriptor when SDL device has support
for any haptic effect, or when UDEV lnxev device has any FF bit set.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winebus.sys/bus_sdl.c | 21 +++++++--
dlls/winebus.sys/bus_udev.c | 15 +++++++
dlls/winebus.sys/hid.c | 75 +++++++++++++++++++++++++++++++++
dlls/winebus.sys/unix_private.h | 8 ++++
dlls/winebus.sys/unixlib.c | 12 ++++++
5 files changed, 128 insertions(+), 3 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 17032e1dba9..bd06717165d 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -115,6 +115,9 @@ static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick);
#define WINE_SDL_HAPTIC_RUMBLE 0x80000000 /* using SDL_HapticRumble API */
#define EFFECT_SUPPORT_HAPTICS (SDL_HAPTIC_LEFTRIGHT|WINE_SDL_HAPTIC_RUMBLE|WINE_SDL_JOYSTICK_RUMBLE)
+#define EFFECT_SUPPORT_PHYSICAL (SDL_HAPTIC_CONSTANT|SDL_HAPTIC_RAMP|SDL_HAPTIC_SINE|SDL_HAPTIC_TRIANGLE| \
+ SDL_HAPTIC_SAWTOOTHUP|SDL_HAPTIC_SAWTOOTHDOWN|SDL_HAPTIC_SPRING|SDL_HAPTIC_DAMPER|SDL_HAPTIC_INERTIA| \
+ SDL_HAPTIC_FRICTION|SDL_HAPTIC_CUSTOM)
struct sdl_device
{
@@ -165,14 +168,12 @@ static void set_hat_value(struct unix_device *iface, int index, int value)
static BOOL descriptor_add_haptic(struct sdl_device *impl)
{
- unsigned int haptics_mask = SDL_HAPTIC_LEFTRIGHT;
-
if (!pSDL_JoystickIsHaptic(impl->sdl_joystick) ||
!(impl->sdl_haptic = pSDL_HapticOpenFromJoystick(impl->sdl_joystick)))
impl->effect_support = 0;
else
{
- impl->effect_support = pSDL_HapticQuery(impl->sdl_haptic) & haptics_mask;
+ impl->effect_support = pSDL_HapticQuery(impl->sdl_haptic);
if (pSDL_HapticRumbleSupported(impl->sdl_haptic))
impl->effect_support |= WINE_SDL_HAPTIC_RUMBLE;
@@ -189,6 +190,12 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
return FALSE;
}
+ if ((impl->effect_support & EFFECT_SUPPORT_PHYSICAL))
+ {
+ if (!hid_device_add_physical(&impl->unix_device))
+ return FALSE;
+ }
+
impl->haptic_effect_id = -1;
return TRUE;
}
@@ -391,12 +398,20 @@ NTSTATUS sdl_device_haptics_start(struct unix_device *iface, DWORD duration_ms,
return STATUS_SUCCESS;
}
+static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, USAGE control)
+{
+ FIXME("iface %p, control %#04x stub\n", iface, control);
+
+ return STATUS_NOT_SUPPORTED;
+}
+
static const struct hid_device_vtbl sdl_device_vtbl =
{
sdl_device_destroy,
sdl_device_start,
sdl_device_stop,
sdl_device_haptics_start,
+ sdl_device_physical_device_control,
};
static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 909d91667e1..e4c0103b270 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -658,6 +658,13 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
impl->haptic_effect_id = effect.id;
}
+ for (i = 0; i < FF_MAX; ++i) if (test_bit(ffbits, i)) break;
+ if (i != FF_MAX)
+ {
+ if (!hid_device_add_physical(iface))
+ return STATUS_NO_MEMORY;
+ }
+
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
@@ -802,12 +809,20 @@ static NTSTATUS lnxev_device_haptics_start(struct unix_device *iface, DWORD dura
return STATUS_SUCCESS;
}
+static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, USAGE control)
+{
+ FIXME("iface %p, control %#04x stub!\n", iface, control);
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
static const struct hid_device_vtbl lnxev_device_vtbl =
{
lnxev_device_destroy,
lnxev_device_start,
lnxev_device_stop,
lnxev_device_haptics_start,
+ lnxev_device_physical_device_control,
};
#endif /* HAS_PROPER_INPUT_HEADER */
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 0c8e85dfc5f..12db1706ede 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -35,6 +35,7 @@
#include "ddk/hidsdi.h"
#include "wine/debug.h"
+#include "wine/hid.h"
#include "unix_private.h"
@@ -394,6 +395,64 @@ BOOL hid_device_add_haptics(struct unix_device *iface)
return hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template));
}
+#include "pshpack1.h"
+struct pid_device_control
+{
+ BYTE control_index;
+};
+
+static const USAGE pid_device_control_usages[] =
+{
+ 0, /* HID nary collection indexes start at 1 */
+ PID_USAGE_DC_ENABLE_ACTUATORS,
+ PID_USAGE_DC_DISABLE_ACTUATORS,
+ PID_USAGE_DC_STOP_ALL_EFFECTS,
+ PID_USAGE_DC_DEVICE_RESET,
+ PID_USAGE_DC_DEVICE_PAUSE,
+ PID_USAGE_DC_DEVICE_CONTINUE,
+};
+#include "poppack.h"
+
+BOOL hid_device_add_physical(struct unix_device *iface)
+{
+ struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
+ const BYTE device_control_report = ++desc->next_report_id[HidP_Output];
+ const BYTE device_control_header[] =
+ {
+ USAGE_PAGE(1, HID_USAGE_PAGE_PID),
+ USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
+ COLLECTION(1, Logical),
+ REPORT_ID(1, device_control_report),
+
+ USAGE(1, PID_USAGE_DEVICE_CONTROL),
+ COLLECTION(1, Logical),
+ };
+ const BYTE device_control_footer[] =
+ {
+ LOGICAL_MINIMUM(1, 1),
+ LOGICAL_MAXIMUM(1, 6),
+ REPORT_SIZE(1, 8),
+ REPORT_COUNT(1, 1),
+ OUTPUT(1, Data|Ary|Abs),
+ END_COLLECTION,
+ END_COLLECTION,
+ };
+ ULONG i;
+
+ if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header)))
+ return FALSE;
+ for (i = 1; i < ARRAY_SIZE(pid_device_control_usages); ++i)
+ {
+ if (!hid_report_descriptor_append_usage(desc, pid_device_control_usages[i]))
+ return FALSE;
+ }
+ if (!hid_report_descriptor_append(desc, device_control_footer, sizeof(device_control_footer)))
+ return FALSE;
+
+ iface->hid_physical.device_control_report = device_control_report;
+ return TRUE;
+}
+
#include "pop_hid_macros.h"
static void hid_device_destroy(struct unix_device *iface)
@@ -425,6 +484,7 @@ NTSTATUS hid_device_get_report_descriptor(struct unix_device *iface, BYTE *buffe
static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io)
{
+ struct hid_physical *physical = &iface->hid_physical;
struct hid_haptics *haptics = &iface->hid_haptics;
if (packet->reportId == haptics->waveform_report)
@@ -450,6 +510,21 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
io->Status = iface->hid_vtbl->haptics_start(iface, duration_ms, rumble->intensity, buzz->intensity);
}
}
+ else if (packet->reportId == physical->device_control_report)
+ {
+ struct pid_device_control *report = (struct pid_device_control *)(packet->reportBuffer + 1);
+ USAGE control;
+
+ io->Information = sizeof(*report) + 1;
+ if (packet->reportBufferLen < io->Information)
+ io->Status = STATUS_BUFFER_TOO_SMALL;
+ else if (report->control_index >= ARRAY_SIZE(pid_device_control_usages))
+ io->Status = STATUS_INVALID_PARAMETER;
+ else if (!(control = pid_device_control_usages[report->control_index]))
+ io->Status = STATUS_INVALID_PARAMETER;
+ else
+ io->Status = iface->hid_vtbl->physical_device_control(iface, control);
+ }
else
{
io->Information = 0;
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 01638bf19fc..c62e4c9d0ab 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -47,6 +47,7 @@ struct hid_device_vtbl
void (*stop)(struct unix_device *iface);
NTSTATUS (*haptics_start)(struct unix_device *iface, DWORD duration_ms,
USHORT rumble_intensity, USHORT buzz_intensity);
+ NTSTATUS (*physical_device_control)(struct unix_device *iface, USAGE control);
};
struct hid_report_descriptor
@@ -87,6 +88,11 @@ struct hid_haptics
BYTE waveform_report;
};
+struct hid_physical
+{
+ BYTE device_control_report;
+};
+
struct hid_device_state
{
ULONG bit_size;
@@ -115,6 +121,7 @@ struct unix_device
struct hid_report_descriptor hid_report_descriptor;
struct hid_device_state hid_device_state;
struct hid_haptics hid_haptics;
+ struct hid_physical hid_physical;
};
extern void *raw_device_create(const struct raw_device_vtbl *vtbl, SIZE_T size) DECLSPEC_HIDDEN;
@@ -152,6 +159,7 @@ extern BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usa
const USAGE *usages, BOOL rel, LONG min, LONG max) DECLSPEC_HIDDEN;
extern BOOL hid_device_add_haptics(struct unix_device *iface) DECLSPEC_HIDDEN;
+extern BOOL hid_device_add_physical(struct unix_device *iface) DECLSPEC_HIDDEN;
extern BOOL hid_device_set_abs_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN;
extern BOOL hid_device_set_rel_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN;
diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c
index 5cf23badf88..49a42ea04ad 100644
--- a/dlls/winebus.sys/unixlib.c
+++ b/dlls/winebus.sys/unixlib.c
@@ -88,12 +88,18 @@ static NTSTATUS mouse_haptics_start(struct unix_device *iface, DWORD duration,
return STATUS_NOT_SUPPORTED;
}
+static NTSTATUS mouse_physical_device_control(struct unix_device *iface, USAGE control)
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
static const struct hid_device_vtbl mouse_vtbl =
{
mouse_destroy,
mouse_start,
mouse_stop,
mouse_haptics_start,
+ mouse_physical_device_control,
};
static const struct device_desc mouse_device_desc =
@@ -145,12 +151,18 @@ static NTSTATUS keyboard_haptics_start(struct unix_device *iface, DWORD duration
return STATUS_NOT_SUPPORTED;
}
+static NTSTATUS keyboard_physical_device_control(struct unix_device *iface, USAGE control)
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
static const struct hid_device_vtbl keyboard_vtbl =
{
keyboard_destroy,
keyboard_start,
keyboard_stop,
keyboard_haptics_start,
+ keyboard_physical_device_control,
};
static const struct device_desc keyboard_device_desc =
--
2.33.0
Oct. 1, 2021
[PATCH 01/10] dinput: Stub hid_joystick force feedback methods.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/dinput/joystick_hid.c | 83 +++++++++++++++++++++++++++++++++++---
dlls/dinput8/tests/hid.c | 11 +----
2 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 834a5de0860..a6c6de3a889 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -780,6 +780,77 @@ static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, D
return S_OK;
}
+static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, const GUID *guid,
+ const DIEFFECT *params, IDirectInputEffect **out,
+ IUnknown *outer )
+{
+ FIXME( "iface %p, guid %s, params %p, out %p, outer %p stub!\n", iface, debugstr_guid( guid ),
+ params, out, outer );
+
+ if (!out) return E_POINTER;
+
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_EnumEffects( IDirectInputDevice8W *iface, LPDIENUMEFFECTSCALLBACKW callback,
+ void *context, DWORD type )
+{
+ FIXME( "iface %p, callback %p, context %p, type %#x stub!\n", iface, callback, context, type );
+
+ if (!callback) return DIERR_INVALIDPARAM;
+
+ return DI_OK;
+}
+
+static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, DIEFFECTINFOW *info,
+ const GUID *guid )
+{
+ FIXME( "iface %p, info %p, guid %s stub!\n", iface, info, debugstr_guid( guid ) );
+
+ if (!info) return E_POINTER;
+ if (info->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM;
+
+ return DIERR_DEVICENOTREG;
+}
+
+static HRESULT WINAPI hid_joystick_GetForceFeedbackState( IDirectInputDevice8W *iface, DWORD *out )
+{
+ FIXME( "iface %p, out %p stub!\n", iface, out );
+
+ if (!out) return E_POINTER;
+
+ return DIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI hid_joystick_SendForceFeedbackCommand( IDirectInputDevice8W *iface, DWORD command )
+{
+ FIXME( "iface %p, command %x stub!\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;
+ }
+
+ return DIERR_INVALIDPARAM;
+}
+
+static HRESULT WINAPI hid_joystick_EnumCreatedEffectObjects( IDirectInputDevice8W *iface,
+ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK callback,
+ void *context, DWORD flags )
+{
+ FIXME( "iface %p, callback %p, context %p, flags %#x stub!\n", iface, callback, context, flags );
+
+ if (!callback) return DIERR_INVALIDPARAM;
+
+ return DIERR_UNSUPPORTED;
+}
+
static HRESULT WINAPI hid_joystick_Poll( IDirectInputDevice8W *iface )
{
struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
@@ -837,12 +908,12 @@ static const IDirectInputDevice8WVtbl hid_joystick_vtbl =
IDirectInputDevice2WImpl_RunControlPanel,
IDirectInputDevice2WImpl_Initialize,
/*** IDirectInputDevice2 methods ***/
- IDirectInputDevice2WImpl_CreateEffect,
- IDirectInputDevice2WImpl_EnumEffects,
- IDirectInputDevice2WImpl_GetEffectInfo,
- IDirectInputDevice2WImpl_GetForceFeedbackState,
- IDirectInputDevice2WImpl_SendForceFeedbackCommand,
- IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
+ hid_joystick_CreateEffect,
+ hid_joystick_EnumEffects,
+ hid_joystick_GetEffectInfo,
+ hid_joystick_GetForceFeedbackState,
+ hid_joystick_SendForceFeedbackCommand,
+ hid_joystick_EnumCreatedEffectObjects,
IDirectInputDevice2WImpl_Escape,
hid_joystick_Poll,
IDirectInputDevice2WImpl_SendDeviceData,
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
index 1ab6e645947..e6439ed8fe5 100644
--- a/dlls/dinput8/tests/hid.c
+++ b/dlls/dinput8/tests/hid.c
@@ -4038,7 +4038,6 @@ static void test_simple_joystick(void)
check_member( objinst, expect_objects[5], "%u", wReportId );
hr = IDirectInputDevice8_EnumEffects( device, NULL, NULL, DIEFT_ALL );
- todo_wine
ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumEffects returned %#x\n", hr );
res = 0;
hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, 0xfe );
@@ -4054,18 +4053,14 @@ static void test_simple_joystick(void)
check_effects_params.expect_count - check_effects_params.index );
hr = IDirectInputDevice8_GetEffectInfo( device, NULL, &GUID_Sine );
- todo_wine
ok( hr == E_POINTER, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr );
effectinfo.dwSize = sizeof(DIEFFECTINFOW) + 1;
hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
- todo_wine
ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr );
effectinfo.dwSize = sizeof(DIEFFECTINFOW);
hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_NULL );
- todo_wine
ok( hr == DIERR_DEVICENOTREG, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr );
hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
- todo_wine
ok( hr == DIERR_DEVICENOTREG, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr );
hr = IDirectInputDevice8_SetDataFormat( device, NULL );
@@ -4645,18 +4640,14 @@ static void test_simple_joystick(void)
winetest_pop_context();
hr = IDirectInputDevice8_GetForceFeedbackState( device, NULL );
- todo_wine
ok( hr == E_POINTER, "IDirectInputDevice8_GetForceFeedbackState returned %#x\n", hr );
res = 0xdeadbeef;
hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
- todo_wine
ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetForceFeedbackState returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
- todo_wine
ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
- todo_wine
ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
objdata[0].dwOfs = 0xd;
@@ -5713,6 +5704,7 @@ static void test_force_feedback_joystick( void )
effectinfo.dwSize = sizeof(DIEFFECTINFOW);
hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
+ todo_wine
ok( hr == DI_OK, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr );
todo_wine
check_member_guid( effectinfo, expect_effects[0], guid );
@@ -5802,7 +5794,6 @@ static void test_force_feedback_joystick( void )
ok( hr == 0x80040301, "IDirectInputDevice8_GetForceFeedbackState returned %#x\n", hr );
hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
- todo_wine
ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SendForceFeedbackCommand returned %#x\n", hr );
set_hid_expect( file, &expect_dc_reset, sizeof(expect_dc_reset) );
--
2.33.0
Oct. 1, 2021
[PATCH] ole32/tests: Remove unused variable.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/tests/moniker.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index abd17c9961f..8d3276651bc 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -1179,7 +1179,6 @@ static void test_MkParseDisplayName(void)
IEnumMoniker *spEM3 = NULL;
DWORD pdwReg1=0;
- DWORD grflags=0;
DWORD pdwReg2=0;
IRunningObjectTable * pprot=NULL;
@@ -1388,13 +1387,10 @@ todo_wine
matchCnt = count_moniker_matches(pbc, spEM1);
- grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
- hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
+ hr = IRunningObjectTable_Register(pprot, ROTFLAGS_REGISTRATIONKEEPSALIVE, lpEM1, pmk1, &pdwReg1);
ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
- grflags=0;
- grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
- hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
+ hr = IRunningObjectTable_Register(pprot, ROTFLAGS_REGISTRATIONKEEPSALIVE, lpEM1, pmk2, &pdwReg2);
ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
--
2.33.0
Oct. 1, 2021