[PATCH 5/6] windows.gaming.input: Implement GetCurrentReading for the RawGameController runtimeclass.

Rémi Bernon rbernon at codeweavers.com
Thu Mar 10 03:38:43 CST 2022


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/windows.gaming.input/controller.c | 16 +++++-
 dlls/windows.gaming.input/provider.c   | 68 ++++++++++++++++++++++++++
 dlls/windows.gaming.input/provider.idl | 11 +++++
 3 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/dlls/windows.gaming.input/controller.c b/dlls/windows.gaming.input/controller.c
index 8bd95c2dead..fb2f4ab82e7 100644
--- a/dlls/windows.gaming.input/controller.c
+++ b/dlls/windows.gaming.input/controller.c
@@ -261,9 +261,21 @@ static HRESULT WINAPI raw_controller_GetCurrentReading( IRawGameController *ifac
                                                         UINT32 switches_size, enum GameControllerSwitchPosition *switches,
                                                         UINT32 axes_size, DOUBLE *axes, UINT64 *timestamp )
 {
-    FIXME( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p stub!\n",
+    struct controller *impl = impl_from_IRawGameController( iface );
+    WineGameControllerState state;
+    HRESULT hr;
+
+    TRACE( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p.\n",
            iface, buttons_size, buttons, switches_size, switches, axes_size, axes, timestamp );
-    return E_NOTIMPL;
+
+    if (FAILED(hr = IWineGameControllerProvider_get_State( impl->wine_provider, &state ))) return hr;
+
+    memcpy( axes, state.axes, axes_size * sizeof(*axes) );
+    memcpy( buttons, state.buttons, buttons_size * sizeof(*buttons) );
+    memcpy( switches, state.switches, switches_size * sizeof(*switches) );
+    *timestamp = state.timestamp;
+
+    return hr;
 }
 
 static HRESULT WINAPI raw_controller_GetSwitchKind( IRawGameController *iface, INT32 index, enum GameControllerSwitchKind *value )
diff --git a/dlls/windows.gaming.input/provider.c b/dlls/windows.gaming.input/provider.c
index 7883ec6af68..56ba005812d 100644
--- a/dlls/windows.gaming.input/provider.c
+++ b/dlls/windows.gaming.input/provider.c
@@ -182,6 +182,69 @@ static HRESULT WINAPI wine_provider_get_SwitchCount( IWineGameControllerProvider
     return hr;
 }
 
+static HRESULT WINAPI wine_provider_get_State( IWineGameControllerProvider *iface, struct WineGameControllerState *out )
+{
+    struct provider *impl = impl_from_IWineGameControllerProvider( iface );
+    DIJOYSTATE2 state;
+    UINT32 i = 0;
+    HRESULT hr;
+
+    TRACE( "iface %p, out %p.\n", iface, out );
+
+    if (FAILED(hr = IDirectInputDevice8_GetDeviceState( impl->dinput_device, sizeof(state), &state )))
+    {
+        WARN( "Failed to read device state, hr %#lx\n", hr );
+        return hr;
+    }
+
+    i = ARRAY_SIZE(state.rgbButtons);
+    while (i--) out->buttons[i] = (state.rgbButtons[i] != 0);
+
+    i = ARRAY_SIZE(state.rgdwPOV);
+    while (i--)
+    {
+        if (state.rgdwPOV[i] == ~0) out->switches[i] = GameControllerSwitchPosition_Center;
+        else out->switches[i] = state.rgdwPOV[i] * 8 / 36000 + 1;
+    }
+
+    i = 0;
+    out->axes[i++] = state.lX / 65535.;
+    out->axes[i++] = state.lY / 65535.;
+    out->axes[i++] = state.lZ / 65535.;
+    out->axes[i++] = state.lRx / 65535.;
+    out->axes[i++] = state.lRy / 65535.;
+    out->axes[i++] = state.lRz / 65535.;
+    out->axes[i++] = state.rglSlider[0] / 65535.;
+    out->axes[i++] = state.rglSlider[1] / 65535.;
+    out->axes[i++] = state.lVX / 65535.;
+    out->axes[i++] = state.lVY / 65535.;
+    out->axes[i++] = state.lVZ / 65535.;
+    out->axes[i++] = state.lVRx / 65535.;
+    out->axes[i++] = state.lVRy / 65535.;
+    out->axes[i++] = state.lVRz / 65535.;
+    out->axes[i++] = state.rglVSlider[0] / 65535.;
+    out->axes[i++] = state.rglVSlider[1] / 65535.;
+    out->axes[i++] = state.lAX / 65535.;
+    out->axes[i++] = state.lAY / 65535.;
+    out->axes[i++] = state.lAZ / 65535.;
+    out->axes[i++] = state.lARx / 65535.;
+    out->axes[i++] = state.lARy / 65535.;
+    out->axes[i++] = state.lARz / 65535.;
+    out->axes[i++] = state.rglASlider[0] / 65535.;
+    out->axes[i++] = state.rglASlider[1] / 65535.;
+    out->axes[i++] = state.lFX / 65535.;
+    out->axes[i++] = state.lFY / 65535.;
+    out->axes[i++] = state.lFZ / 65535.;
+    out->axes[i++] = state.lFRx / 65535.;
+    out->axes[i++] = state.lFRy / 65535.;
+    out->axes[i++] = state.lFRz / 65535.;
+    out->axes[i++] = state.rglFSlider[0] / 65535.;
+    out->axes[i++] = state.rglFSlider[1] / 65535.;
+    out->timestamp = GetTickCount64();
+
+    return S_OK;
+}
+
 static const struct IWineGameControllerProviderVtbl wine_provider_vtbl =
 {
     wine_provider_QueryInterface,
@@ -196,6 +259,7 @@ static const struct IWineGameControllerProviderVtbl wine_provider_vtbl =
     wine_provider_get_AxisCount,
     wine_provider_get_ButtonCount,
     wine_provider_get_SwitchCount,
+    wine_provider_get_State,
 };
 
 DEFINE_IINSPECTABLE( game_provider, IGameControllerProvider, struct provider, IWineGameControllerProvider_iface )
@@ -284,6 +348,10 @@ void provider_create( const WCHAR *device_path )
     IDirectInput8_Release( dinput );
     if (FAILED(hr)) return;
 
+    if (FAILED(hr = IDirectInputDevice8_SetCooperativeLevel( dinput_device, 0, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE ))) goto done;
+    if (FAILED(hr = IDirectInputDevice8_SetDataFormat( dinput_device, &c_dfDIJoystick2 ))) goto done;
+    if (FAILED(hr = IDirectInputDevice8_Acquire( dinput_device ))) goto done;
+
     if (!(impl = calloc( 1, sizeof(*impl) ))) goto done;
     impl->IWineGameControllerProvider_iface.lpVtbl = &wine_provider_vtbl;
     impl->IGameControllerProvider_iface.lpVtbl = &game_provider_vtbl;
diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl
index 19d5643f767..25191078721 100644
--- a/dlls/windows.gaming.input/provider.idl
+++ b/dlls/windows.gaming.input/provider.idl
@@ -32,6 +32,7 @@ import "windows.gaming.input.custom.idl";
 
 namespace Windows.Gaming.Input.Custom {
     typedef enum WineGameControllerType WineGameControllerType;
+    typedef struct WineGameControllerState WineGameControllerState;
     interface IWineGameControllerProvider;
     runtimeclass WineGameControllerProvider;
 
@@ -41,6 +42,14 @@ namespace Windows.Gaming.Input.Custom {
         Gamepad = 1,
     };
 
+    struct WineGameControllerState
+    {
+        UINT64 timestamp;
+        DOUBLE axes[32];
+        BOOLEAN buttons[128];
+        Windows.Gaming.Input.GameControllerSwitchPosition switches[4];
+    };
+
     [
         uuid(06e58977-7684-4dc5-bad1-cda52a4aa06d)
     ]
@@ -62,6 +71,8 @@ namespace Windows.Gaming.Input.Custom {
         [propget] HRESULT AxisCount([out, retval] INT32 *value);
         [propget] HRESULT ButtonCount([out, retval] INT32 *value);
         [propget] HRESULT SwitchCount([out, retval] INT32 *value);
+
+        [propget] HRESULT State([out, retval] WineGameControllerState *state);
     }
 
     [
-- 
2.35.1




More information about the wine-devel mailing list