[PATCH v2 09/10] winmm: Reimplement joystick APIs on top of dinput.

Andrew Eikum aeikum at codeweavers.com
Thu Dec 9 09:33:03 CST 2021


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Fri, Dec 03, 2021 at 12:19:09PM +0100, Rémi Bernon wrote:
> Based on a patch from Zebediah Figura <zfigura at codeweavers.com>.
> 
> Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
> ---
>  dlls/dinput8/tests/hid.c |  51 ------
>  dlls/winmm/Makefile.in   |   2 +-
>  dlls/winmm/joystick.c    | 355 +++++++++++++++++++++++++++++++++------
>  dlls/winmm/winemm.h      |   3 +
>  dlls/winmm/winmm.c       |   2 +
>  5 files changed, 308 insertions(+), 105 deletions(-)
> 
> diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c
> index f82fa9a7cb0..c7bf549deb1 100644
> --- a/dlls/dinput8/tests/hid.c
> +++ b/dlls/dinput8/tests/hid.c
> @@ -9736,10 +9736,6 @@ static void test_winmm_joystick(void)
>      ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
>  
>      ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
> -    /* FIXME: Marvin somehow manages to get a device, ignore it */
> -    if (!strcmp( winetest_platform, "wine") && ret == 0 &&
> -        !wcscmp( caps.szPname, L"QEMU Virtio Tablet" ))
> -        return;
>      ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
>  
>      memset( &caps, 0xcd, sizeof(caps) );
> @@ -9783,7 +9779,6 @@ static void test_winmm_joystick(void)
>      ret = joyGetPosEx( 0, &infoex );
>      /* first call for an index sometimes fail */
>      if (ret == JOYERR_PARMS) ret = joyGetPosEx( 0, &infoex );
> -    todo_wine
>      ok( ret == 0, "joyGetPosEx returned %u\n", ret );
>  
>      ret = joyGetDevCapsW( 1, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
> @@ -9791,43 +9786,29 @@ static void test_winmm_joystick(void)
>  
>      memset( &caps, 0xcd, sizeof(caps) );
>      ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(caps) );
> -    todo_wine
>      ok( ret == 0, "joyGetDevCapsW returned %u\n", ret );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wMid );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wPid );
>      todo_wine
>      check_member_wstr( caps, expect_caps, szPname );
>      check_member( caps, expect_caps, "%#x", wXmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wXmax );
>      check_member( caps, expect_caps, "%#x", wYmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wYmax );
>      check_member( caps, expect_caps, "%#x", wZmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wZmax );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wNumButtons );
>      check_member( caps, expect_caps, "%#x", wPeriodMin );
>      check_member( caps, expect_caps, "%#x", wPeriodMax );
>      check_member( caps, expect_caps, "%#x", wRmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wRmax );
>      check_member( caps, expect_caps, "%#x", wUmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wUmax );
>      check_member( caps, expect_caps, "%#x", wVmin );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wVmax );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wCaps );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wMaxAxes );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wNumAxes );
> -    todo_wine
>      check_member( caps, expect_caps, "%#x", wMaxButtons );
>      check_member_wstr( caps, expect_caps, szRegKey );
>      check_member_wstr( caps, expect_caps, szOEMVxD );
> @@ -9836,7 +9817,6 @@ static void test_winmm_joystick(void)
>      check_member_guid( caps, expect_caps, NameGuid );
>  
>      ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
> -    todo_wine
>      ok( ret == 0, "joyGetDevCapsW returned %u\n", ret );
>      ret = joyGetDevCapsW( 0, NULL, sizeof(JOYCAPSW) );
>      ok( ret == MMSYSERR_INVALPARAM, "joyGetDevCapsW returned %u\n", ret );
> @@ -9858,29 +9838,19 @@ static void test_winmm_joystick(void)
>      infoex.dwSize = sizeof(JOYINFOEX);
>      infoex.dwFlags = JOY_RETURNALL;
>      ret = joyGetPosEx( 0, &infoex );
> -    todo_wine
>      ok( ret == 0, "joyGetPosEx returned %u\n", ret );
>      check_member( infoex, expect_infoex[0], "%#x", dwSize );
>      check_member( infoex, expect_infoex[0], "%#x", dwFlags );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwXpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwYpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwZpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwRpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwUpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwVpos );
>      check_member( infoex, expect_infoex[0], "%#x", dwButtons );
>      check_member( infoex, expect_infoex[0], "%#x", dwButtonNumber );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwPOV );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwReserved1 );
> -    todo_wine
>      check_member( infoex, expect_infoex[0], "%#x", dwReserved2 );
>  
>      infoex.dwSize = sizeof(JOYINFOEX) - 4;
> @@ -9893,13 +9863,9 @@ static void test_winmm_joystick(void)
>      ok( ret == JOYERR_PARMS, "joyGetPos returned %u\n", ret );
>      memset( &info, 0xcd, sizeof(info) );
>      ret = joyGetPos( 0, &info );
> -    todo_wine
>      ok( ret == 0, "joyGetPos returned %u\n", ret );
> -    todo_wine
>      check_member( info, expect_info, "%#x", wXpos );
> -    todo_wine
>      check_member( info, expect_info, "%#x", wYpos );
> -    todo_wine
>      check_member( info, expect_info, "%#x", wZpos );
>      check_member( info, expect_info, "%#x", wButtons );
>  
> @@ -9933,24 +9899,16 @@ static void test_winmm_joystick(void)
>      infoex.dwSize = sizeof(JOYINFOEX);
>      infoex.dwFlags = JOY_RETURNALL;
>      ret = joyGetPosEx( 0, &infoex );
> -    todo_wine
>      ok( ret == 0, "joyGetPosEx returned %u\n", ret );
>      check_member( infoex, expect_infoex[1], "%#x", dwSize );
>      check_member( infoex, expect_infoex[1], "%#x", dwFlags );
>      check_member( infoex, expect_infoex[1], "%#x", dwXpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwYpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwZpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwRpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwUpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwVpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwButtons );
> -    todo_wine
>      check_member( infoex, expect_infoex[1], "%#x", dwButtonNumber );
>      check_member( infoex, expect_infoex[1], "%#x", dwPOV );
>  
> @@ -9963,26 +9921,17 @@ static void test_winmm_joystick(void)
>      infoex.dwSize = sizeof(JOYINFOEX);
>      infoex.dwFlags = JOY_RETURNALL;
>      ret = joyGetPosEx( 0, &infoex );
> -    todo_wine
>      ok( ret == 0, "joyGetPosEx returned %u\n", ret );
>      check_member( infoex, expect_infoex[2], "%#x", dwSize );
>      check_member( infoex, expect_infoex[2], "%#x", dwFlags );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwXpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwYpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwZpos );
>      check_member( infoex, expect_infoex[2], "%#x", dwRpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwUpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwVpos );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwButtons );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwButtonNumber );
> -    todo_wine
>      check_member( infoex, expect_infoex[2], "%#x", dwPOV );
>  
>      ret = IDirectInputDevice8_Release( device );
> diff --git a/dlls/winmm/Makefile.in b/dlls/winmm/Makefile.in
> index 3036526c14e..5439ae21678 100644
> --- a/dlls/winmm/Makefile.in
> +++ b/dlls/winmm/Makefile.in
> @@ -1,7 +1,7 @@
>  EXTRADEFS = -D_WINMM_
>  MODULE    = winmm.dll
>  IMPORTLIB = winmm
> -IMPORTS   = uuid user32 advapi32 ole32 msacm32
> +IMPORTS   = uuid user32 advapi32 ole32 msacm32 dinput8
>  
>  C_SRCS = \
>  	driver.c \
> diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c
> index 20a69e8119d..5f5683e3e35 100644
> --- a/dlls/winmm/joystick.c
> +++ b/dlls/winmm/joystick.c
> @@ -1,10 +1,11 @@
> -/* -*- tab-width: 8; c-basic-offset: 4 -*- */
>  /*
>   * joystick functions
>   *
>   * Copyright 1997 Andreas Mohr
> - *	     2000 Wolfgang Schwotzer
> - *                Eric Pouech
> + * Copyright 2000 Wolfgang Schwotzer
> + * Copyright 2000 Eric Pouech
> + * Copyright 2020 Zebediah Figura for CodeWeavers
> + * Copyright 2021 Rémi Bernon for CodeWeavers
>   *
>   * This library is free software; you can redistribute it and/or
>   * modify it under the terms of the GNU Lesser General Public
> @@ -22,6 +23,7 @@
>   */
>  
>  #include <stdarg.h>
> +#include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -30,11 +32,11 @@
>  #include "windef.h"
>  #include "winbase.h"
>  #include "mmsystem.h"
> -#include "wingdi.h"
> -#include "winuser.h"
> -#include "winnls.h"
>  
> -#include "mmddk.h"
> +#include "initguid.h"
> +#include "dinput.h"
> +
> +#include "winemm.h"
>  
>  #include "wine/debug.h"
>  
> @@ -49,19 +51,185 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
>  };
>  static CRITICAL_SECTION joystick_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
>  
> +struct joystick_state
> +{
> +    LONG x;
> +    LONG y;
> +    LONG z;
> +    LONG u;
> +    LONG v;
> +    LONG r;
> +    LONG pov;
> +    BYTE buttons[32];
> +};
> +
> +static const DIOBJECTDATAFORMAT object_formats[] =
> +{
> +    { &GUID_XAxis, offsetof(struct joystick_state, x), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_YAxis, offsetof(struct joystick_state, y), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_ZAxis, offsetof(struct joystick_state, z), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_RzAxis, offsetof(struct joystick_state, r), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_Slider, offsetof(struct joystick_state, u), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_RxAxis, offsetof(struct joystick_state, v), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION },
> +    { &GUID_POV, offsetof(struct joystick_state, pov), DIDFT_OPTIONAL|DIDFT_POV|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[0]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[1]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[2]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[3]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[4]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[5]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[6]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[7]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[8]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[9]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[10]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[11]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[12]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[13]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[14]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[15]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[16]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[17]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[18]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[19]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[20]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[21]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[22]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[23]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[24]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[25]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[26]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[27]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[28]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[29]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[30]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +    { NULL, offsetof(struct joystick_state, buttons[31]), DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE, 0 },
> +};
> +
> +static const DIDATAFORMAT data_format =
> +{
> +    .dwSize = sizeof(DIDATAFORMAT),
> +    .dwObjSize = sizeof(DIOBJECTDATAFORMAT),
> +    .dwFlags = DIDF_ABSAXIS,
> +    .dwDataSize = sizeof(struct joystick_state),
> +    .dwNumObjs = ARRAY_SIZE(object_formats),
> +    .rgodf = (DIOBJECTDATAFORMAT *)object_formats,
> +};
> +
>  #define JOY_PERIOD_MIN	(10)	/* min Capture time period */
>  #define JOY_PERIOD_MAX	(1000)	/* max Capture time period */
>  
> -typedef struct tagWINE_JOYSTICK {
> +struct joystick
> +{
> +    DIDEVICEINSTANCEW instance;
> +    IDirectInputDevice8W *device;
> +    struct joystick_state state;
> +    HANDLE event;
> +
>      JOYINFO info;
>      HWND capture;
>      UINT timer;
>      DWORD threshold;
>      BOOL changed;
> -    HDRVR driver;
> -} WINE_JOYSTICK;
> +    ULONG last_check;
> +};
>  
> -static WINE_JOYSTICK joysticks[16];
> +static DIDEVICEINSTANCEW instances[16];
> +static struct joystick joysticks[16];
> +static IDirectInput8W *dinput;
> +
> +static BOOL CALLBACK enum_instances( const DIDEVICEINSTANCEW *instance, void *context )
> +{
> +    ULONG index = *(ULONG *)context;
> +    BYTE type = instance->dwDevType;
> +
> +    if (type == DI8DEVTYPE_MOUSE) return DIENUM_CONTINUE;
> +    if (type == DI8DEVTYPE_KEYBOARD) return DIENUM_CONTINUE;
> +
> +    instances[index++] = *instance;
> +    if (index >= ARRAY_SIZE(instances)) return DIENUM_STOP;
> +    *(ULONG *)context = index;
> +    return DIENUM_CONTINUE;
> +}
> +
> +void joystick_load( HINSTANCE instance )
> +{
> +    HRESULT hr = DirectInput8Create( instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W,
> +                                     (void **)&dinput, NULL );
> +    if (FAILED(hr)) WARN( "could not create dinput instance, hr %#x\n", hr );
> +}
> +
> +void joystick_unload()
> +{
> +    int i;
> +
> +    if (!dinput) return;
> +
> +    for (i = 0; i < ARRAY_SIZE(joysticks); i++)
> +    {
> +        if (!joysticks[i].device) continue;
> +        IDirectInputDevice8_Release( joysticks[i].device );
> +        CloseHandle( joysticks[i].event );
> +    }
> +
> +    IDirectInput8_Release( dinput );
> +}
> +
> +static void find_joysticks(void)
> +{
> +    IDirectInputDevice8W *device;
> +    HANDLE event;
> +    DWORD index;
> +    HRESULT hr;
> +
> +    if (!dinput) return;
> +
> +    index = 0;
> +    IDirectInput8_EnumDevices( dinput, DI8DEVCLASS_ALL, enum_instances, &index, DIEDFL_ATTACHEDONLY );
> +    TRACE( "found %u device instances\n", index );
> +
> +    while (index--)
> +    {
> +        if (!memcmp( &joysticks[index].instance, &instances[index], sizeof(DIDEVICEINSTANCEW) ))
> +            continue;
> +
> +        if (joysticks[index].device)
> +        {
> +            IDirectInputDevice8_Release( joysticks[index].device );
> +            CloseHandle( joysticks[index].event );
> +        }
> +
> +        if (!(event = CreateEventW( NULL, FALSE, FALSE, NULL )))
> +            WARN( "could not event for device, error %u\n", GetLastError() );
> +        else if (FAILED(hr = IDirectInput8_CreateDevice( dinput, &instances[index].guidInstance, &device, NULL )))
> +            WARN( "could not create device %s instance, hr %#x\n",
> +                  debugstr_guid( &instances[index].guidInstance ), hr );
> +        else if (FAILED(hr = IDirectInputDevice8_SetEventNotification( device, event )))
> +            WARN( "SetEventNotification device %p hr %#x\n", device, hr );
> +        else if (FAILED(hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_NONEXCLUSIVE|DISCL_BACKGROUND )))
> +            WARN( "SetCooperativeLevel device %p hr %#x\n", device, hr );
> +        else if (FAILED(hr = IDirectInputDevice8_SetDataFormat( device, &data_format )))
> +            WARN( "SetDataFormat device %p hr %#x\n", device, hr );
> +        else if (FAILED(hr = IDirectInputDevice8_Acquire( device )))
> +            WARN( "Acquire device %p hr %#x\n", device, hr );
> +        else
> +        {
> +            TRACE( "opened device %p event %p\n", device, event );
> +
> +            memset( &joysticks[index], 0, sizeof(struct joystick) );
> +            joysticks[index].instance = instances[index];
> +            joysticks[index].device = device;
> +            joysticks[index].event = event;
> +            continue;
> +        }
> +
> +        CloseHandle( event );
> +        if (device) IDirectInputDevice8_Release( device );
> +        memmove( joysticks + index, joysticks + index + 1,
> +                 (ARRAY_SIZE(joysticks) - index - 1) * sizeof(struct joystick) );
> +        memset( &joysticks[ARRAY_SIZE(joysticks) - 1], 0, sizeof(struct joystick) );
> +    }
> +}
>  
>  static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
>  {
> @@ -69,29 +237,6 @@ static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
>      return diff <= max_diff;
>  }
>  
> -/**************************************************************************
> - * 				JOY_LoadDriver		[internal]
> - */
> -static	BOOL JOY_LoadDriver(DWORD dwJoyID)
> -{
> -    static BOOL winejoystick_missing = FALSE;
> -
> -    if (dwJoyID >= ARRAY_SIZE(joysticks) || winejoystick_missing) return FALSE;
> -    if (joysticks[dwJoyID].driver) return TRUE;
> -
> -    joysticks[dwJoyID].driver = OpenDriverA( "winejoystick.drv", 0, dwJoyID );
> -
> -    if (!joysticks[dwJoyID].driver)
> -    {
> -        WARN("OpenDriverA(\"winejoystick.drv\") failed\n");
> -
> -        /* The default driver is missing, don't attempt to load it again */
> -        winejoystick_missing = TRUE;
> -    }
> -
> -    return (joysticks[dwJoyID].driver != 0);
> -}
> -
>  static void CALLBACK joystick_timer( HWND hwnd, UINT msg, UINT_PTR timer, DWORD time )
>  {
>      MMRESULT res;
> @@ -163,6 +308,22 @@ UINT WINAPI DECLSPEC_HOTPATCH joyGetNumDevs(void)
>   */
>  MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, JOYCAPSW *caps, UINT size )
>  {
> +    DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)};
> +    DIDEVCAPS dicaps = {.dwSize = sizeof(DIDEVCAPS)};
> +    DIPROPDWORD diprop =
> +    {
> +        .diph =
> +        {
> +            .dwSize = sizeof(DIPROPDWORD),
> +            .dwHeaderSize = sizeof(DIPROPHEADER),
> +            .dwHow = DIPH_DEVICE,
> +        },
> +    };
> +    MMRESULT res = JOYERR_NOERROR;
> +    IDirectInputDevice8W *device;
> +    ULONG ticks = GetTickCount();
> +    HRESULT hr;
> +
>      TRACE( "id %d, caps %p, size %u.\n", (int)id, caps, size );
>  
>      if (!caps) return MMSYSERR_INVALPARAM;
> @@ -173,12 +334,67 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsW( UINT_PTR id, JOYCAPSW *caps, U
>      if (id == ~(UINT_PTR)0) return JOYERR_NOERROR;
>  
>      if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS;
> -    if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
>  
> -    caps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */
> -    caps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */
> +    EnterCriticalSection( &joystick_cs );
>  
> -    return SendDriverMessage( joysticks[id].driver, JDD_GETDEVCAPS, (LPARAM)caps, size );
> +    if (!(device = joysticks[id].device) && (ticks - joysticks[id].last_check) >= 2000)
> +    {
> +        joysticks[id].last_check = ticks;
> +        find_joysticks();
> +    }
> +
> +    if (!(device = joysticks[id].device)) res = JOYERR_PARMS;
> +    else if (FAILED(hr = IDirectInputDevice8_GetCapabilities( device, &dicaps )))
> +    {
> +        WARN( "GetCapabilities device %p returned %#x\n", device, hr );
> +        res = JOYERR_PARMS;
> +    }
> +    else
> +    {
> +        hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &diprop.diph );
> +        if (FAILED(hr)) WARN( "GetProperty device %p returned %#x\n", device, hr );
> +        else
> +        {
> +            caps->wMid = LOWORD(diprop.dwData);
> +            caps->wPid = HIWORD(diprop.dwData);
> +        }
> +
> +        wcscpy( caps->szPname, L"Wine joystick driver" );
> +        caps->wXmin = 0;
> +        caps->wXmax = 0xffff;
> +        caps->wYmin = 0;
> +        caps->wYmax = 0xffff;
> +        caps->wZmin = 0;
> +        caps->wZmax = 0xffff;
> +        caps->wNumButtons = dicaps.dwButtons;
> +        caps->wPeriodMin = JOY_PERIOD_MIN;
> +        caps->wPeriodMax = JOY_PERIOD_MAX;
> +        caps->wRmin = 0;
> +        caps->wRmax = 0xffff;
> +        caps->wUmin = 0;
> +        caps->wUmax = 0xffff;
> +        caps->wVmin = 0;
> +        caps->wVmax = 0xffff;
> +        caps->wCaps = 0;
> +        caps->wMaxAxes = 6;
> +        caps->wNumAxes = min( dicaps.dwAxes, caps->wMaxAxes );
> +        caps->wMaxButtons = 32;
> +
> +        hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, z), DIPH_BYOFFSET );
> +        if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASZ;
> +        hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, r), DIPH_BYOFFSET );
> +        if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASR;
> +        hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, u), DIPH_BYOFFSET );
> +        if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASU;
> +        hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, v), DIPH_BYOFFSET );
> +        if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASV;
> +        hr = IDirectInputDevice8_GetObjectInfo( device, &instance, offsetof(struct joystick_state, pov), DIPH_BYOFFSET );
> +        if (SUCCEEDED(hr)) caps->wCaps |= JOYCAPS_HASPOV|JOYCAPS_POV4DIR;
> +    }
> +
> +    LeaveCriticalSection( &joystick_cs );
> +
> +    return res;
>  }
>  
>  /**************************************************************************
> @@ -243,25 +459,60 @@ MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetDevCapsA( UINT_PTR id, JOYCAPSA *caps, U
>   */
>  MMRESULT WINAPI DECLSPEC_HOTPATCH joyGetPosEx( UINT id, JOYINFOEX *info )
>  {
> +    DWORD i, ticks = GetTickCount();
> +    MMRESULT res = JOYERR_NOERROR;
> +    IDirectInputDevice8W *device;
> +    struct joystick_state state;
> +    HRESULT hr;
> +
>      TRACE( "id %u, info %p.\n", id, info );
>  
>      if (!info) return MMSYSERR_INVALPARAM;
>      if (id >= ARRAY_SIZE(joysticks) || info->dwSize < sizeof(JOYINFOEX)) return JOYERR_PARMS;
> -    if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
>  
> -    info->dwXpos = 0;
> -    info->dwYpos = 0;
> -    info->dwZpos = 0;
> -    info->dwRpos = 0;
> -    info->dwUpos = 0;
> -    info->dwVpos = 0;
> -    info->dwButtons = 0;
> -    info->dwButtonNumber = 0;
> -    info->dwPOV = 0;
> -    info->dwReserved1 = 0;
> -    info->dwReserved2 = 0;
> +    EnterCriticalSection( &joystick_cs );
>  
> -    return SendDriverMessage( joysticks[id].driver, JDD_GETPOSEX, (LPARAM)info, 0 );
> +    if (!(device = joysticks[id].device) && (ticks - joysticks[id].last_check) >= 2000)
> +    {
> +        joysticks[id].last_check = ticks;
> +        find_joysticks();
> +    }
> +
> +    if (!(device = joysticks[id].device))
> +        res = JOYERR_PARMS;
> +    else if (FAILED(hr = IDirectInputDevice8_GetDeviceState( device, sizeof(struct joystick_state), &state )))
> +    {
> +        WARN( "GetDeviceState device %p returned %#x\n", device, hr );
> +        res = JOYERR_PARMS;
> +    }
> +    else
> +    {
> +        if (info->dwFlags & JOY_RETURNX) info->dwXpos = state.x;
> +        if (info->dwFlags & JOY_RETURNY) info->dwYpos = state.y;
> +        if (info->dwFlags & JOY_RETURNZ) info->dwZpos = state.z;
> +        if (info->dwFlags & JOY_RETURNR) info->dwRpos = state.r;
> +        if (info->dwFlags & JOY_RETURNU) info->dwUpos = state.u;
> +        if (info->dwFlags & JOY_RETURNV) info->dwVpos = state.v;
> +        if (info->dwFlags & JOY_RETURNPOV)
> +        {
> +            if (state.pov == ~0) info->dwPOV = 0xffff;
> +            else info->dwPOV = state.pov;
> +        }
> +        if (info->dwFlags & JOY_RETURNBUTTONS)
> +        {
> +            info->dwButtonNumber = info->dwButtons = 0;
> +            for (i = 0; i < ARRAY_SIZE(state.buttons); ++i)
> +            {
> +                if (!state.buttons[i]) continue;
> +                info->dwButtonNumber++;
> +                info->dwButtons |= 1 << i;
> +            }
> +        }
> +    }
> +
> +    LeaveCriticalSection( &joystick_cs );
> +
> +    return res;
>  }
>  
>  /**************************************************************************
> @@ -313,7 +564,6 @@ MMRESULT WINAPI joyReleaseCapture( UINT id )
>      TRACE( "id %u.\n", id );
>  
>      if (id >= ARRAY_SIZE(joysticks)) return JOYERR_PARMS;
> -    if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
>  
>      EnterCriticalSection( &joystick_cs );
>  
> @@ -343,7 +593,6 @@ MMRESULT WINAPI joySetCapture( HWND hwnd, UINT id, UINT period, BOOL changed )
>      if (id >= ARRAY_SIZE(joysticks) || hwnd == 0) return JOYERR_PARMS;
>      if (period < JOY_PERIOD_MIN) period = JOY_PERIOD_MIN;
>      else if (period > JOY_PERIOD_MAX) period = JOY_PERIOD_MAX;
> -    if (!JOY_LoadDriver( id )) return MMSYSERR_NODRIVER;
>  
>      EnterCriticalSection( &joystick_cs );
>  
> diff --git a/dlls/winmm/winemm.h b/dlls/winmm/winemm.h
> index d7bab0f531d..3459c2a85ef 100644
> --- a/dlls/winmm/winemm.h
> +++ b/dlls/winmm/winemm.h
> @@ -153,6 +153,9 @@ MMRESULT WINMM_CheckCallback(DWORD_PTR dwCallback, DWORD fdwOpen, BOOL mixer) DE
>  
>  void WINMM_DeleteWaveform(void) DECLSPEC_HIDDEN;
>  
> +void joystick_load( HMODULE instance ) DECLSPEC_HIDDEN;
> +void joystick_unload( void ) DECLSPEC_HIDDEN;
> +
>  /* Global variables */
>  extern CRITICAL_SECTION WINMM_cs DECLSPEC_HIDDEN;
>  extern HINSTANCE hWinMM32Instance DECLSPEC_HIDDEN;
> diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c
> index eea29ea61e5..aab8bfb51a9 100644
> --- a/dlls/winmm/winmm.c
> +++ b/dlls/winmm/winmm.c
> @@ -145,11 +145,13 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
>          if (!WINMM_CreateIData(hInstDLL))
>              return FALSE;
>  
> +        joystick_load( hInstDLL );
>          break;
>      case DLL_PROCESS_DETACH:
>          if(fImpLoad)
>              break;
>  
> +        joystick_unload();
>          MCI_SendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, 0L);
>          MMDRV_Exit();
>          DRIVER_UnloadAll();
> -- 
> 2.34.0
> 
> 



More information about the wine-devel mailing list