[PATCH v2 1/5] dinput: Introduce new HID joystick backend.

Zebediah Figura (she/her) zfigura at codeweavers.com
Tue Jun 29 11:26:56 CDT 2021



On 6/29/21 8:15 AM, Rémi Bernon wrote:
> This adds a new joystick backend, implemented on top of HID and without
> any host dependencies. This will be progressively implementated, and
> it's not going to be usable until at least a few more patches.
> 
> Because of that, and because it may also introduce regressions compared
> to the existing backends, it is disabled by default and is optionally
> enabled using the following global registry key:
> 
>    [HKCU\\Software\\Wine\\DirectInput\\Joysticks]
>    "HID"="enabled"
> 
> Or using the corresponding AppDefaults registry key:
> 
>    [HKCU\\Software\\Wine\\AppDefaults\\<app.exe>\\DirectInput\\Joysticks]
>    "HID"="enabled"
> 
> This setting will be removed later, when it becomes usable enough, to
> use the individual device disable mechanism available in joy.cpl.
> 
> Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
> ---
> 
> v2: Make the backend disabled by default, optionally enabled in the
>      registry. This is only temporary until we have at least input
>      support.
> 
>   dlls/dinput/Makefile.in           |   3 +-
>   dlls/dinput/dinput_main.c         |   3 +-
>   dlls/dinput/dinput_private.h      |   1 +
>   dlls/dinput/joystick.c            |  17 +-
>   dlls/dinput/joystick_hid.c        | 450 ++++++++++++++++++++++++++++++
>   dlls/dinput/joystick_linux.c      |   2 +-
>   dlls/dinput/joystick_linuxinput.c |   2 +-
>   dlls/dinput/joystick_private.h    |   2 +-
>   dlls/dinput8/Makefile.in          |   3 +-
>   9 files changed, 472 insertions(+), 11 deletions(-)
>   create mode 100644 dlls/dinput/joystick_hid.c
> 
> diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in
> index a22c8a72180..f2347927ed6 100644
> --- a/dlls/dinput/Makefile.in
> +++ b/dlls/dinput/Makefile.in
> @@ -1,6 +1,6 @@
>   MODULE    = dinput.dll
>   IMPORTLIB = dinput
> -IMPORTS   = dinput dxguid uuid comctl32 ole32 user32 advapi32
> +IMPORTS   = dinput dxguid uuid comctl32 ole32 user32 advapi32 hid
>   EXTRADEFS = -DDIRECTINPUT_VERSION=0x0700
>   EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
>   
> @@ -12,6 +12,7 @@ C_SRCS = \
>   	dinput_main.c \
>   	effect_linuxinput.c \
>   	joystick.c \
> +	joystick_hid.c \
>   	joystick_linux.c \
>   	joystick_linuxinput.c \
>   	joystick_osx.c \
> diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
> index c7b932aca44..88ee1855675 100644
> --- a/dlls/dinput/dinput_main.c
> +++ b/dlls/dinput/dinput_main.c
> @@ -80,7 +80,8 @@ static const struct dinput_device *dinput_devices[] =
>       &keyboard_device,
>       &joystick_linuxinput_device,
>       &joystick_linux_device,
> -    &joystick_osx_device
> +    &joystick_osx_device,
> +    &joystick_hid_device,
>   };
>   
>   HINSTANCE DINPUT_instance;
> diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
> index 7e0f56c68df..c11b64585d9 100644
> --- a/dlls/dinput/dinput_private.h
> +++ b/dlls/dinput/dinput_private.h
> @@ -67,6 +67,7 @@ struct DevicePlayer {
>   
>   extern const struct dinput_device mouse_device DECLSPEC_HIDDEN;
>   extern const struct dinput_device keyboard_device DECLSPEC_HIDDEN;
> +extern const struct dinput_device joystick_hid_device DECLSPEC_HIDDEN;
>   extern const struct dinput_device joystick_linux_device DECLSPEC_HIDDEN;
>   extern const struct dinput_device joystick_linuxinput_device DECLSPEC_HIDDEN;
>   extern const struct dinput_device joystick_osx_device DECLSPEC_HIDDEN;
> diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
> index 8ea7850621c..60153d0d0f3 100644
> --- a/dlls/dinput/joystick.c
> +++ b/dlls/dinput/joystick.c
> @@ -271,13 +271,13 @@ void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
>       }
>   }
>   
> -BOOL device_disabled_registry(const char* name)
> +BOOL device_disabled_registry(const char* name, BOOL disable)
>   {
>       static const char disabled_str[] = "disabled";
> +    static const char enabled_str[] = "enabled";
>       static const char joystick_key[] = "Joysticks";
>       char buffer[MAX_PATH];
>       HKEY hkey, appkey, temp;
> -    BOOL do_disable = FALSE;
>   
>       get_app_key(&hkey, &appkey);
>   
> @@ -297,16 +297,23 @@ BOOL device_disabled_registry(const char* name)
>   
>       /* Look for the "controllername"="disabled" key */
>       if (!get_config_key(hkey, appkey, name, buffer, sizeof(buffer)))
> -        if (!strcmp(disabled_str, buffer))
> +    {
> +        if (!disable && !strcmp(disabled_str, buffer))
>           {
>               TRACE("Disabling joystick '%s' based on registry key.\n", name);
> -            do_disable = TRUE;
> +            disable = TRUE;
> +        }
> +        else if (disable && !strcmp(enabled_str, buffer))
> +        {
> +            TRACE("Enabling joystick '%s' based on registry key.\n", name);
> +            disable = FALSE;
>           }
> +    }
>   
>       if (appkey) RegCloseKey(appkey);
>       if (hkey)   RegCloseKey(hkey);
>   
> -    return do_disable;
> +    return disable;
>   }
>   
>   BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
> diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
> new file mode 100644
> index 00000000000..fadc7d9efe4
> --- /dev/null
> +++ b/dlls/dinput/joystick_hid.c
> @@ -0,0 +1,450 @@
> +/*  DirectInput HID Joystick device
> + *
> + * 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
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> + */
> +
> +#include <assert.h>
> +#include <stdarg.h>
> +#include <string.h>
> +
> +#include "windef.h"
> +#include "winbase.h"
> +#include "winternl.h"
> +#include "winuser.h"
> +#include "winerror.h"
> +#include "winreg.h"
> +
> +#include "ddk/hidsdi.h"
> +#include "devguid.h"
> +#include "dinput.h"
> +#include "setupapi.h"
> +
> +#include "wine/debug.h"
> +
> +#include "dinput_private.h"
> +#include "device_private.h"
> +#include "joystick_private.h"
> +
> +#include "initguid.h"
> +
> +WINE_DEFAULT_DEBUG_CHANNEL(dinput);
> +
> +DEFINE_GUID( hid_joystick_guid, 0x9e573edb, 0x7734, 0x11d2, 0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7 );
> +
> +struct hid_joystick
> +{
> +    IDirectInputDeviceImpl base;
> +
> +    HANDLE device;
> +    PHIDP_PREPARSED_DATA preparsed;
> +};
> +
> +static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface )
> +{
> +    return CONTAINING_RECORD( CONTAINING_RECORD( iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface ),
> +                              struct hid_joystick, base );
> +}
> +
> +static ULONG WINAPI hid_joystick_Release( IDirectInputDevice8W *iface )
> +{
> +    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
> +    struct hid_joystick tmp = *impl;
> +    ULONG res;
> +
> +    if (!(res = IDirectInputDevice2WImpl_Release( iface )))
> +    {
> +        HidD_FreePreparsedData( tmp.preparsed );
> +        CloseHandle( tmp.device );
> +    }
> +
> +    return res;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetCapabilities( IDirectInputDevice8W *iface, DIDEVCAPS *caps )
> +{
> +    FIXME( "iface %p, caps %p stub!\n", iface, caps );
> +
> +    if (!caps) return E_POINTER;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_EnumObjects( IDirectInputDevice8W *iface, LPDIENUMDEVICEOBJECTSCALLBACKW callback,
> +                                                void *ref, DWORD flags )
> +{
> +    FIXME( "iface %p, callback %p, ref %p, flags %#x stub!\n", iface, callback, ref, flags );
> +
> +    if (!callback) return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetProperty( IDirectInputDevice8W *iface, REFGUID guid, DIPROPHEADER *header )
> +{
> +    FIXME( "iface %p, guid %s, header %p stub!\n", iface, debugstr_guid( guid ), header );
> +
> +    if (!header) return DIERR_INVALIDPARAM;
> +    if (!IS_DIPROP( guid )) return DI_OK;
> +
> +    switch (LOWORD( guid ))
> +    {
> +    default: return IDirectInputDevice2WImpl_GetProperty( iface, guid, header );
> +    }
> +}
> +
> +static HRESULT WINAPI hid_joystick_SetProperty( IDirectInputDevice8W *iface, REFGUID guid, const DIPROPHEADER *header )
> +{
> +    FIXME( "iface %p, guid %s, header %p stub!\n", iface, debugstr_guid( guid ), header );
> +
> +    if (!header) return DIERR_INVALIDPARAM;
> +    if (!IS_DIPROP( guid )) return DI_OK;
> +
> +    switch (LOWORD( guid ))
> +    {
> +    default: return IDirectInputDevice2WImpl_SetProperty( iface, guid, header );
> +    }
> +}
> +
> +static HRESULT WINAPI hid_joystick_Acquire( IDirectInputDevice8W *iface )
> +{
> +    HRESULT hr;
> +
> +    TRACE( "iface %p.\n", iface );
> +
> +    if ((hr = IDirectInputDevice2WImpl_Acquire( iface )) != DI_OK) return hr;
> +
> +    return DI_OK;
> +}
> +
> +static HRESULT WINAPI hid_joystick_Unacquire( IDirectInputDevice8W *iface )
> +{
> +    HRESULT hr;
> +
> +    TRACE( "iface %p.\n", iface );
> +
> +    if ((hr = IDirectInputDevice2WImpl_Unacquire( iface )) != DI_OK) return hr;
> +
> +    return DI_OK;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetDeviceState( IDirectInputDevice8W *iface, DWORD len, void *ptr )
> +{
> +    FIXME( "iface %p, len %u, ptr %p stub!\n", iface, len, ptr );
> +
> +    if (!ptr) return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetObjectInfo( IDirectInputDevice8W *iface, DIDEVICEOBJECTINSTANCEW *instance,
> +                                                  DWORD obj, DWORD how )
> +{
> +    FIXME( "iface %p, instance %p, obj %#x, how %#x stub!\n", iface, instance, obj, how );
> +
> +    if (!instance) return E_POINTER;
> +    if (instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W) &&
> +        instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW))
> +        return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetDeviceInfo( IDirectInputDevice8W *iface, DIDEVICEINSTANCEW *instance )
> +{
> +    FIXME( "iface %p, instance %p stub!\n", iface, instance );
> +
> +    if (!instance) return E_POINTER;
> +    if (instance->dwSize != sizeof(DIDEVICEINSTANCE_DX3W) &&
> +        instance->dwSize != sizeof(DIDEVICEINSTANCEW))
> +        return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_CreateEffect( IDirectInputDevice8W *iface, REFGUID rguid,
> +                                                 const DIEFFECT *effect, IDirectInputEffect **out,
> +                                                 IUnknown *outer )
> +{
> +    FIXME( "iface %p, rguid %s, effect %p, out %p, outer %p stub!\n", iface, debugstr_guid( rguid ),
> +           effect, out, outer );
> +
> +    if (!out) return E_POINTER;
> +    if (!rguid || !effect) return DI_NOEFFECT;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_EnumEffects( IDirectInputDevice8W *iface, LPDIENUMEFFECTSCALLBACKW callback,
> +                                                void *ref, DWORD type )
> +{
> +    FIXME( "iface %p, callback %p, ref %p, type %#x stub!\n", iface, callback, ref, type );
> +
> +    if (!callback) return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, DIEFFECTINFOW *info, REFGUID guid )
> +{
> +    FIXME( "iface %p, info %p, guid %s stub!\n", iface, info, debugstr_guid( guid ) );
> +
> +    if (!info) return E_POINTER;
> +
> +    return E_NOTIMPL;
> +}
> +
> +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 E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_SendForceFeedbackCommand( IDirectInputDevice8W *iface, DWORD flags )
> +{
> +    FIXME( "iface %p, flags %x stub!\n", iface, flags );
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_EnumCreatedEffectObjects( IDirectInputDevice8W *iface,
> +                                                             LPDIENUMCREATEDEFFECTOBJECTSCALLBACK callback,
> +                                                             void *ref, DWORD flags )
> +{
> +    FIXME( "iface %p, callback %p, ref %p, flags %#x stub!\n", iface, callback, ref, flags );
> +
> +    if (!callback) return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_BuildActionMap( IDirectInputDevice8W *iface, DIACTIONFORMATW *format,
> +                                                   const WCHAR *username, DWORD flags )
> +{
> +    FIXME( "iface %p, format %p, username %s, flags %#x stub!\n", iface, format, debugstr_w(username), flags );
> +
> +    if (!format) return DIERR_INVALIDPARAM;
> +
> +    return E_NOTIMPL;
> +}
> +
> +static HRESULT WINAPI hid_joystick_SetActionMap( IDirectInputDevice8W *iface, DIACTIONFORMATW *format,
> +                                                 const WCHAR *username, DWORD flags )
> +{
> +    struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface );
> +
> +    TRACE( "iface %p, format %p, username %s, flags %#x.\n", iface, format, debugstr_w(username), flags );
> +
> +    if (!format) return DIERR_INVALIDPARAM;
> +
> +    return _set_action_map( iface, format, username, flags, impl->base.data_format.wine_df );
> +}
> +
> +static const IDirectInputDevice8WVtbl hid_joystick_vtbl =
> +{
> +    /*** IUnknown methods ***/
> +    IDirectInputDevice2WImpl_QueryInterface,
> +    IDirectInputDevice2WImpl_AddRef,
> +    hid_joystick_Release,
> +    /*** IDirectInputDevice methods ***/
> +    hid_joystick_GetCapabilities,
> +    hid_joystick_EnumObjects,
> +    hid_joystick_GetProperty,
> +    hid_joystick_SetProperty,
> +    hid_joystick_Acquire,
> +    hid_joystick_Unacquire,
> +    hid_joystick_GetDeviceState,
> +    IDirectInputDevice2WImpl_GetDeviceData,
> +    IDirectInputDevice2WImpl_SetDataFormat,
> +    IDirectInputDevice2WImpl_SetEventNotification,
> +    IDirectInputDevice2WImpl_SetCooperativeLevel,
> +    hid_joystick_GetObjectInfo,
> +    hid_joystick_GetDeviceInfo,
> +    IDirectInputDevice2WImpl_RunControlPanel,
> +    IDirectInputDevice2WImpl_Initialize,
> +    /*** IDirectInputDevice2 methods ***/
> +    hid_joystick_CreateEffect,
> +    hid_joystick_EnumEffects,
> +    hid_joystick_GetEffectInfo,
> +    hid_joystick_GetForceFeedbackState,
> +    hid_joystick_SendForceFeedbackCommand,
> +    hid_joystick_EnumCreatedEffectObjects,
> +    IDirectInputDevice2WImpl_Escape,
> +    IDirectInputDevice2WImpl_Poll,
> +    IDirectInputDevice2WImpl_SendDeviceData,
> +    /*** IDirectInputDevice7 methods ***/
> +    IDirectInputDevice7WImpl_EnumEffectsInFile,
> +    IDirectInputDevice7WImpl_WriteEffectToFile,
> +    /*** IDirectInputDevice8 methods ***/
> +    hid_joystick_BuildActionMap,
> +    hid_joystick_SetActionMap,
> +    IDirectInputDevice8WImpl_GetImageInfo,
> +};
> +
> +static HRESULT hid_joystick_device_open( DWORD index, WCHAR *device_path, HANDLE *device, DWORD version,
> +                                         PHIDP_PREPARSED_DATA *preparsed, HIDD_ATTRIBUTES *attrs,
> +                                         HIDP_CAPS *caps, DIDEVICEINSTANCEW *instance )
> +{
> +    RAWINPUTDEVICELIST *list;
> +    DWORD count, i, j;
> +
> +    GetRawInputDeviceList( NULL, &count, sizeof(*list) );
> +    if (!(list = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*list) ))) return DIERR_OUTOFMEMORY;
> +    GetRawInputDeviceList( list, &count, sizeof(*list) );

Can't the count change between these two calls?

> +
> +    for (i = 0; i < count; ++i) if (list[i].dwType == RIM_TYPEHID) break;
> +    for (j = 0; j < index && i < count; ++i) if (list[i].dwType == RIM_TYPEHID) ++j;
> +    if (i == count)
> +    {
> +        HeapFree( GetProcessHeap(), 0, list );
> +        return DIERR_DEVICENOTREG;
> +    }

This is very confusing. The first loop seems redundant; the variable 
naming is unclear; and the nesting of three levels on the same line is 
hard to read. Could I propose something like the following instead?

DWORD hid_count = 0, i;

for (i = 0; i < count; ++i)
{
     if (list[i].dwType == RIM_TYPEHID && hid_count++ == req_index)
         break;
}
if (i == count)
{
     ...
}

(Personally I always like to take this for/if/break pattern and make it 
into a helper function, but I won't complain if not.)

> +
> +    count = MAX_PATH;
> +    GetRawInputDeviceInfoW( list[i].hDevice, RIDI_DEVICENAME, device_path, &count );
> +    HeapFree( GetProcessHeap(), 0, list );
> +
> +    TRACE( "Opening %s\n", debugstr_w(device_path) );
> +    *device = CreateFileW( device_path, GENERIC_READ | GENERIC_WRITE,
> +                           FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
> +    *preparsed = NULL;
> +
> +    if (*device == INVALID_HANDLE_VALUE) return DI_NOTATTACHED;
> +    if (!HidD_GetPreparsedData( *device, preparsed )) goto failed;
> +    if (!HidD_GetAttributes( *device, attrs )) goto failed;
> +    if (HidP_GetCaps( *preparsed, caps ) != HIDP_STATUS_SUCCESS) goto failed;
> +
> +    if (caps->UsagePage == HID_USAGE_PAGE_GAME) FIXME( "Unimplemented HID game usage page!\n" );
> +    if (caps->UsagePage == HID_USAGE_PAGE_SIMULATION) FIXME( "Unimplemented HID simulation usage page!\n" );
> +    if (caps->UsagePage != HID_USAGE_PAGE_GENERIC) goto failed;
> +    if (caps->Usage != HID_USAGE_GENERIC_GAMEPAD && caps->Usage != HID_USAGE_GENERIC_JOYSTICK) goto failed;
> +
> +    instance->guidInstance = hid_joystick_guid;
> +    instance->guidInstance.Data3 = index;
> +    instance->guidProduct = DInput_PIDVID_Product_GUID;
> +    instance->guidProduct.Data1 = MAKELONG( attrs->VendorID, attrs->ProductID );
> +    instance->dwDevType = get_device_type( version, caps->Usage != HID_USAGE_GENERIC_GAMEPAD ) | DIDEVTYPE_HID;
> +    instance->guidFFDriver = GUID_NULL;
> +    instance->wUsagePage = caps->UsagePage;
> +    instance->wUsage = caps->Usage;
> +
> +    if (!HidD_GetProductString( *device, instance->tszInstanceName, MAX_PATH )) goto failed;
> +    if (!HidD_GetProductString( *device, instance->tszProductName, MAX_PATH )) goto failed;
> +    return DI_OK;
> +
> +failed:
> +    CloseHandle( *device );
> +    *device = INVALID_HANDLE_VALUE;
> +    HidD_FreePreparsedData( *preparsed );
> +    *preparsed = NULL;
> +    return DI_NOTATTACHED;
> +}
> +
> +static HRESULT hid_joystick_enum_device( DWORD type, DWORD flags, DIDEVICEINSTANCEW *instance,
> +                                         DWORD version, int index )
> +{
> +    HIDD_ATTRIBUTES attrs = {sizeof(attrs)};
> +    PHIDP_PREPARSED_DATA preparsed;
> +    WCHAR device_path[MAX_PATH];
> +    HIDP_CAPS caps;
> +    HANDLE device;
> +    HRESULT hr;
> +
> +    TRACE( "type %x, flags %#x, instance %p, version %04x, index %d\n", type, flags, instance, version, index );
> +
> +    hr = hid_joystick_device_open( index, device_path, &device, version,
> +                                   &preparsed, &attrs, &caps, instance );
> +    if (hr != DI_OK) return hr;
> +
> +    HidD_FreePreparsedData( preparsed );
> +    CloseHandle( device );
> +
> +    if (instance->dwSize != sizeof(DIDEVICEINSTANCEW))
> +        return S_FALSE;
> +    if (version < 0x0800 && type != DIDEVTYPE_JOYSTICK)
> +        return S_FALSE;
> +    if (version >= 0x0800 && type != DI8DEVCLASS_ALL && type != DI8DEVCLASS_GAMECTRL)
> +        return S_FALSE;
> +
> +    if (device_disabled_registry( "HID", TRUE ))
> +        return DIERR_DEVICENOTREG;
> +
> +    TRACE( "Found device with usage %04x:%04x, type %x, instance %s %s, product %s %s, ffdriver %s\n",
> +           instance->wUsagePage, instance->wUsage, instance->dwDevType, debugstr_guid( &instance->guidProduct ),
> +           debugstr_w( instance->tszProductName ), debugstr_guid( &instance->guidInstance ),
> +           debugstr_w( instance->tszInstanceName ), debugstr_guid( &instance->guidFFDriver ) );
> +
> +    return DI_OK;
> +}
> +
> +static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, REFGUID guid, IDirectInputDevice8W **out )
> +{
> +    DIDEVICEINSTANCEW instance = {sizeof(instance)};
> +    DWORD index, size = sizeof(struct hid_joystick);
> +    HIDD_ATTRIBUTES attrs = {sizeof(attrs)};
> +    struct hid_joystick *impl = NULL;
> +    PHIDP_PREPARSED_DATA preparsed;
> +    DIDATAFORMAT *format = NULL;
> +    WCHAR device_path[MAX_PATH];
> +    GUID tmp_guid = *guid;
> +    HIDP_CAPS caps;
> +    HANDLE device;
> +    HRESULT hr;
> +
> +    TRACE( "dinput %p, guid %s, out %p\n", dinput, debugstr_guid( guid ), out );
> +
> +    *out = NULL;
> +    tmp_guid.Data3 = hid_joystick_guid.Data3;
> +    if (!IsEqualGUID( &hid_joystick_guid, &tmp_guid )) return DIERR_DEVICENOTREG;
> +    index = guid->Data3;
> +
> +    hr = hid_joystick_device_open( index, device_path, &device, dinput->dwVersion,
> +                                   &preparsed, &attrs, &caps, &instance );
> +    if (hr != DI_OK) return hr;
> +
> +    hr = direct_input_device_alloc( size, &hid_joystick_vtbl, guid, dinput, (void **)&impl );
> +    if (FAILED(hr)) goto failed;
> +
> +    impl->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": hid_joystick.base.crit");
> +    impl->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
> +
> +    impl->device = device;
> +    impl->preparsed = preparsed;
> +
> +    if (!(format = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*format) ))) goto failed;
> +    impl->base.data_format.wine_df = format;
> +
> +    TRACE( "Created %p\n", impl );
> +
> +    *out = &impl->base.IDirectInputDevice8W_iface;
> +    return DI_OK;
> +
> +failed:
> +    HeapFree( GetProcessHeap(), 0, format );
> +    HeapFree( GetProcessHeap(), 0, impl );
> +    HidD_FreePreparsedData( preparsed );
> +    CloseHandle( device );
> +    return hr;
> +}
> +
> +const struct dinput_device joystick_hid_device =
> +{
> +    "Wine HID joystick driver",
> +    hid_joystick_enum_device,
> +    hid_joystick_create_device,
> +};
> diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
> index 3215978c995..312ef3d9c42 100644
> --- a/dlls/dinput/joystick_linux.c
> +++ b/dlls/dinput/joystick_linux.c
> @@ -175,7 +175,7 @@ static INT find_joystick_devices(void)
>           /* Append driver name */
>           strcat(joydev.name, JOYDEVDRIVER);
>   
> -        if (device_disabled_registry(joydev.name)) {
> +        if (device_disabled_registry(joydev.name, FALSE)) {
>               close(fd);
>               continue;
>           }
> diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
> index 2b970271ec3..558c8cc19e5 100644
> --- a/dlls/dinput/joystick_linuxinput.c
> +++ b/dlls/dinput/joystick_linuxinput.c
> @@ -264,7 +264,7 @@ static void find_joydevs(void)
>           else
>               joydev.name = joydev.device;
>   
> -        if (device_disabled_registry(joydev.name)) {
> +        if (device_disabled_registry(joydev.name, FALSE)) {
>               close(fd);
>               HeapFree(GetProcessHeap(), 0, joydev.name);
>               if (joydev.name != joydev.device)
> diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
> index 874bf3e69a7..9cc30605234 100644
> --- a/dlls/dinput/joystick_private.h
> +++ b/dlls/dinput/joystick_private.h
> @@ -57,7 +57,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
>   
>   DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
>   
> -BOOL device_disabled_registry(const char* name) DECLSPEC_HIDDEN;
> +BOOL device_disabled_registry(const char* name, BOOL disable) DECLSPEC_HIDDEN;
>   
>   ULONG WINAPI JoystickWGenericImpl_Release(LPDIRECTINPUTDEVICE8W iface);
>   
> diff --git a/dlls/dinput8/Makefile.in b/dlls/dinput8/Makefile.in
> index 35b3bfb75f5..71eecd770b3 100644
> --- a/dlls/dinput8/Makefile.in
> +++ b/dlls/dinput8/Makefile.in
> @@ -1,6 +1,6 @@
>   MODULE    = dinput8.dll
>   IMPORTLIB = dinput8
> -IMPORTS   = dinput8 dxguid uuid comctl32 ole32 user32 advapi32
> +IMPORTS   = dinput8 dxguid uuid comctl32 ole32 user32 advapi32 hid
>   EXTRADEFS = -DDIRECTINPUT_VERSION=0x0800
>   EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
>   PARENTSRC = ../dinput
> @@ -13,6 +13,7 @@ C_SRCS = \
>   	dinput_main.c \
>   	effect_linuxinput.c \
>   	joystick.c \
> +	joystick_hid.c \
>   	joystick_linux.c \
>   	joystick_linuxinput.c \
>   	joystick_osx.c \
> 



More information about the wine-devel mailing list