[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