Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure.ac | 1 - dlls/dinput/Makefile.in | 6 - dlls/dinput/device.c | 34 +- dlls/dinput/device_private.h | 27 - dlls/dinput/dinput_main.c | 3 - dlls/dinput/dinput_private.h | 3 - dlls/dinput/effect_linuxinput.c | 906 --------------- dlls/dinput/joystick.c | 962 ---------------- dlls/dinput/joystick_hid.c | 8 +- dlls/dinput/joystick_linux.c | 831 -------------- dlls/dinput/joystick_linuxinput.c | 1276 --------------------- dlls/dinput/joystick_osx.c | 1704 ----------------------------- dlls/dinput/joystick_private.h | 91 -- dlls/dinput8/Makefile.in | 6 - 14 files changed, 6 insertions(+), 5852 deletions(-) delete mode 100644 dlls/dinput/effect_linuxinput.c delete mode 100644 dlls/dinput/joystick.c delete mode 100644 dlls/dinput/joystick_linux.c delete mode 100644 dlls/dinput/joystick_linuxinput.c delete mode 100644 dlls/dinput/joystick_osx.c delete mode 100644 dlls/dinput/joystick_private.h
diff --git a/configure.ac b/configure.ac index 530785c0033..a157c948fec 100644 --- a/configure.ac +++ b/configure.ac @@ -740,7 +740,6 @@ case $host_os in dnl declare needed frameworks AC_SUBST(COREFOUNDATION_LIBS,"-framework CoreFoundation") AC_SUBST(IOKIT_LIBS,"-framework IOKit -framework CoreFoundation") - AC_SUBST(FORCEFEEDBACK_LIBS,"-framework ForceFeedback -framework CoreFoundation") AC_SUBST(APPLICATIONSERVICES_LIBS,"-framework ApplicationServices") AC_SUBST(CORESERVICES_LIBS,"-framework CoreServices") AC_SUBST(APPKIT_LIBS,"-framework AppKit") diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in index 0db023ee7fe..7bd5951a7a1 100644 --- a/dlls/dinput/Makefile.in +++ b/dlls/dinput/Makefile.in @@ -2,7 +2,6 @@ MODULE = dinput.dll IMPORTLIB = dinput IMPORTS = dinput dxguid uuid comctl32 ole32 user32 advapi32 hid setupapi EXTRADEFS = -DDIRECTINPUT_VERSION=0x0700 -EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
EXTRADLLFLAGS = -mcygwin
@@ -12,12 +11,7 @@ C_SRCS = \ data_formats.c \ device.c \ dinput_main.c \ - effect_linuxinput.c \ - joystick.c \ joystick_hid.c \ - joystick_linux.c \ - joystick_linuxinput.c \ - joystick_osx.c \ keyboard.c \ mouse.c
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 484fe904c2e..65698ad64f5 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -187,11 +187,6 @@ void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) { } }
-void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) { - TRACE(" - enumerating : %s ('%s') - %2d - 0x%08x - %s - 0x%x\n", - debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, ddoi->tszName, ddoi->dwFlags); -} - void _dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW *ddoi) { TRACE(" - enumerating : %s ('%s'), - %2d - 0x%08x - %s - 0x%x\n", debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName), ddoi->dwFlags); @@ -437,7 +432,7 @@ void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df } }
-void release_DataFormat(DataFormat * format) +static void release_DataFormat( DataFormat *format ) { TRACE("Deleting DataFormat: %p\n", format);
@@ -637,20 +632,7 @@ static int verify_offset(const DataFormat *df, int offset) return -1; }
-/* find an object by its offset in a data format */ -static int offset_to_object(const DataFormat *df, int offset) -{ - int i; - - if (!df->offsets) return -1; - - for (i = 0; i < df->wine_df->dwNumObjs; i++) - if (df->offsets[i] == offset) return i; - - return -1; -} - -int id_to_object(LPCDIDATAFORMAT df, int id) +static int id_to_object( LPCDIDATAFORMAT df, int id ) { int i;
@@ -669,18 +651,6 @@ static int id_to_offset(const DataFormat *df, int id) return obj >= 0 && df->offsets ? df->offsets[obj] : -1; }
-int find_property(const DataFormat *df, LPCDIPROPHEADER ph) -{ - switch (ph->dwHow) - { - case DIPH_BYID: return id_to_object(df->wine_df, ph->dwObj); - case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj); - } - FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow); - - return -1; -} - static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) { DWORD type = (0x0000ff00 & dwSemantic) >> 8; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 2b939fd5a0c..321a9702642 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -102,43 +102,16 @@ extern BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *over
/* Routines to do DataFormat / WineFormat conversions */ extern void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df) DECLSPEC_HIDDEN; -extern void release_DataFormat(DataFormat *df) DECLSPEC_HIDDEN; extern void queue_event( IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq ) DECLSPEC_HIDDEN; -/* Helper functions to work with data format */ -extern int id_to_object(LPCDIDATAFORMAT df, int id) DECLSPEC_HIDDEN; -extern int find_property(const DataFormat *df, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN; - -/* Common joystick stuff */ -typedef struct -{ - LONG lDevMin; - LONG lDevMax; - LONG lMin; - LONG lMax; - LONG lDeadZone; - LONG lSaturation; -} ObjProps; - -extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN; -extern LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN; - -typedef struct -{ - struct list entry; - LPDIRECTINPUTEFFECT ref; -} effect_list_item;
extern const GUID dinput_pidvid_guid DECLSPEC_HIDDEN;
/* Various debug tools */ extern void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) DECLSPEC_HIDDEN; -extern void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) DECLSPEC_HIDDEN; extern void _dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW *ddoi) DECLSPEC_HIDDEN; extern void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) DECLSPEC_HIDDEN; extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN;
-extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN; - extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN; extern HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 9c0e3875c00..88f338a426d 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -78,9 +78,6 @@ static const struct dinput_device *dinput_devices[] = { &mouse_device, &keyboard_device, - &joystick_linuxinput_device, - &joystick_linux_device, - &joystick_osx_device, &joystick_hid_device, };
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index c11b64585d9..949e84957d0 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -68,9 +68,6 @@ 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;
extern void dinput_hooks_acquire_device(LPDIRECTINPUTDEVICE8W iface); extern void dinput_hooks_unacquire_device(LPDIRECTINPUTDEVICE8W iface); diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c deleted file mode 100644 index 486163aeffa..00000000000 --- a/dlls/dinput/effect_linuxinput.c +++ /dev/null @@ -1,906 +0,0 @@ -/* DirectInput Linux Event Device Effect - * - * Copyright 2005 Daniel Remenak - * - * Thanks to Google's Summer of Code Program (2005) - * - * 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 "config.h" - -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - -#include <stdarg.h> -#include <string.h> -#ifdef HAVE_LINUX_INPUT_H -# include <linux/input.h> -# undef SW_MAX -#endif -#include <limits.h> -#include <errno.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#include <math.h> -#include "wine/debug.h" -#include "wine/unicode.h" -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "dinput.h" - -#include "device_private.h" -#include "joystick_private.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dinput); - -static const IDirectInputEffectVtbl LinuxInputEffectVtbl; -typedef struct LinuxInputEffectImpl LinuxInputEffectImpl; -struct LinuxInputEffectImpl -{ - IDirectInputEffect IDirectInputEffect_iface; - LONG ref; - GUID guid; - - struct ff_effect effect; /* Effect data */ - int gain; /* Effect gain */ - BOOL first_axis_is_x; - int* fd; /* Parent device */ - struct list *entry; /* Entry into the parent's list of effects */ -}; - -static inline LinuxInputEffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface) -{ - return CONTAINING_RECORD(iface, LinuxInputEffectImpl, IDirectInputEffect_iface); -} - -static double ff_effect_direction_to_rad(unsigned int dir) -{ - return (dir & 0xffff) * M_PI / 0x8000; -} - -static void ff_dump_effect(struct ff_effect *effect) -{ - const char *type = "(Unknown)", *length = "INFINITE"; - struct ff_envelope *env = NULL; - double angle; -#define FE(x) case x: type = #x; break - switch (effect->type) - { - FE(FF_RUMBLE); - FE(FF_PERIODIC); - FE(FF_CONSTANT); - FE(FF_SPRING); - FE(FF_FRICTION); - FE(FF_DAMPER); - FE(FF_INERTIA); - FE(FF_RAMP); - } -#undef FE - - /* rotate so 0 points right */ - angle = 360 - ff_effect_direction_to_rad(effect->direction + 0xc000) * 180 / M_PI; - - if (effect->replay.length) - length = wine_dbg_sprintf("%u ms", effect->replay.length); - - TRACE("type 0x%x %s, id %d, direction 0x%x (source angle %.2f), time length %s, start delay %u ms\n", - effect->type, type, effect->id, effect->direction, angle, length, effect->replay.delay); - if (effect->trigger.button || effect->trigger.interval) - TRACE(" -> trigger button %u, re-trigger interval %u ms\n", - effect->trigger.button, effect->trigger.interval); - - if (effect->type == FF_PERIODIC) - { - struct ff_periodic_effect *per = &effect->u.periodic; - const char *wave = "(Unknown)"; -#define FE(x) case x: wave = #x; break - switch (per->waveform) - { - FE(FF_SQUARE); - FE(FF_TRIANGLE); - FE(FF_SINE); - FE(FF_SAW_UP); - FE(FF_SAW_DOWN); - FE(FF_CUSTOM); - } -#undef FE - angle = ff_effect_direction_to_rad(per->phase) * 180 / M_PI; - TRACE(" -> waveform 0x%x %s, period %u ms, magnitude %d, offset %d, phase 0x%x (angle %.2f), custom len %d\n", - per->waveform, wave, per->period, per->magnitude, per->offset, per->phase, angle, per->custom_len); - env = &per->envelope; - } - else if (effect->type == FF_CONSTANT) - { - struct ff_constant_effect *cons = &effect->u.constant; - TRACE(" -> level %d\n", cons->level); - env = &cons->envelope; - } - else if (effect->type == FF_RAMP) - { - struct ff_ramp_effect *ramp = &effect->u.ramp; - TRACE(" -> start/end level %d/%d\n", ramp->start_level, ramp->end_level); - env = &ramp->envelope; - } - else if (effect->type == FF_RUMBLE) - { - struct ff_rumble_effect *rumble = &effect->u.rumble; - TRACE(" -> strong/weak magnitude %u/%u\n", rumble->strong_magnitude, rumble->weak_magnitude); - } - else if (effect->type == FF_SPRING || effect->type == FF_FRICTION || - effect->type == FF_DAMPER || effect->type == FF_INERTIA) - { - struct ff_condition_effect *cond = effect->u.condition; - int i; - for (i = 0; i < 2; i++) - { - /* format numbers here to make them align correctly */ - TRACE(" -> [%d] right/left saturation %5u/%5u, right/left coefficient %5d/%5d," - " deadband %5u, center %5d\n", i, cond[i].right_saturation, cond[i].left_saturation, - cond[i].right_coeff, cond[i].left_coeff, cond[i].deadband, cond[i].center); - } - } - - if (env) - TRACE(" -> envelope attack length(ms)/level %u/%u, fade length(ms)/level %u/%u\n", - env->attack_length, env->attack_level, env->fade_length, env->fade_level); -} - -/****************************************************************************** - * LinuxInputEffectImpl - */ - -static ULONG WINAPI LinuxInputEffectImpl_AddRef( - LPDIRECTINPUTEFFECT iface) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE( "(%p) ref %d\n", This, ref ); - return ref; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Download( - LPDIRECTINPUTEFFECT iface) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - int ret, old_effect_id; - - TRACE("(this=%p)\n", This); - ff_dump_effect(&This->effect); - - old_effect_id = This->effect.id; - if (ioctl(*(This->fd), EVIOCSFF, &This->effect) != -1) - return DI_OK; - - /* Linux kernel < 3.14 has a bug that incorrectly assigns an effect ID even - * on error, restore it here if that is the case. */ - This->effect.id = old_effect_id; - - switch (errno) - { - case EINVAL: - ret = DIERR_INVALIDPARAM; - break; - case ENOSPC: - ret = DIERR_DEVICEFULL; - break; - case ENOMEM: - ret = DIERR_OUTOFMEMORY; - break; - default: - ret = DIERR_INPUTLOST; - break; - } - TRACE("Could not upload effect to fd %d, errno %d "%s", returning 0x%x.\n", - *This->fd, errno, strerror(errno), ret); - return ret; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Escape( - LPDIRECTINPUTEFFECT iface, - LPDIEFFESCAPE pesc) -{ - WARN("(this=%p,%p): invalid: no hardware-specific escape codes in this" - " driver!\n", iface, pesc); - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_GetEffectGuid( - LPDIRECTINPUTEFFECT iface, - LPGUID pguid) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("(this=%p,%p)\n", This, pguid); - - *pguid = This->guid; - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus( - LPDIRECTINPUTEFFECT iface, - LPDWORD pdwFlags) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("(this=%p,%p)\n", This, pdwFlags); - - if (!pdwFlags) - return E_POINTER; - - if (This->effect.id == -1) - return DIERR_NOTDOWNLOADED; - - /* linux sends the effect status through an event. - * that event is trapped by our parent joystick driver - * and there is no clean way to pass it back to us. */ - FIXME("Not enough information to provide a status.\n"); - - (*pdwFlags) = 0; - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_GetParameters( - LPDIRECTINPUTEFFECT iface, - LPDIEFFECT peff, - DWORD dwFlags) -{ - HRESULT diErr = DI_OK; - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags); - - /* Major conversion factors are: - * times: millisecond (linux) -> microsecond (windows) (x * 1000) - * forces: scale 0x7FFF (linux) -> scale 10000 (windows) approx ((x / 33) * 10) - * angles: scale 0x7FFF (linux) -> scale 35999 (windows) approx ((x / 33) * 36) - * angle bases: 0 -> -y (down) (linux) -> 0 -> +x (right) (windows) - */ - - if (dwFlags & DIEP_AXES) { - if (peff->cAxes < 2 /* linuxinput effects always use 2 axes, x and y */) - diErr = DIERR_MOREDATA; - peff->cAxes = 2; - if (diErr) - return diErr; - else { - peff->rgdwAxes[0] = DIJOFS_X; - peff->rgdwAxes[1] = DIJOFS_Y; - } - } - - if (dwFlags & DIEP_DIRECTION) { - if (peff->cAxes < 2) - diErr = DIERR_MOREDATA; - peff->cAxes = 2; - if (diErr) - return diErr; - else { - if (peff->dwFlags & DIEFF_CARTESIAN) { - /* rotate so 0 points right */ - double angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000); - peff->rglDirection[0] = sin(angle) * 1000; - peff->rglDirection[1] = -cos(angle) * 1000; - } else { - /* Polar and spherical coordinates are the same for two or less - * axes. - * Note that we also use this case if NO flags are marked. - * According to MSDN, we should return the direction in the - * format that it was specified in, if no flags are marked. - */ - peff->rglDirection[0] = (This->effect.direction / 33) * 36 + 9000; - if (peff->rglDirection[0] > 35999) - peff->rglDirection[0] -= 35999; - } - } - } - - if (dwFlags & DIEP_DURATION) - { - if (!This->effect.replay.length) /* infinite for the linux driver */ - peff->dwDuration = INFINITE; - else - peff->dwDuration = (DWORD)This->effect.replay.length * 1000; - } - - if (dwFlags & DIEP_ENVELOPE) { - struct ff_envelope* env; - if (This->effect.type == FF_CONSTANT) env = &This->effect.u.constant.envelope; - else if (This->effect.type == FF_PERIODIC) env = &This->effect.u.periodic.envelope; - else if (This->effect.type == FF_RAMP) env = &This->effect.u.ramp.envelope; - else env = NULL; - if (env == NULL) { - peff->lpEnvelope = NULL; - } else if (peff->lpEnvelope == NULL) { - return DIERR_INVALIDPARAM; - } else { - peff->lpEnvelope->dwAttackLevel = (env->attack_level / 33) * 10; - peff->lpEnvelope->dwAttackTime = env->attack_length * 1000; - peff->lpEnvelope->dwFadeLevel = (env->fade_level / 33) * 10; - peff->lpEnvelope->dwFadeTime = env->fade_length * 1000; - } - } - - if (dwFlags & DIEP_GAIN) { - peff->dwGain = This->gain * 10000 / 0xFFFF; - } - - if (dwFlags & DIEP_SAMPLEPERIOD) { - /* the linux input ff driver has no support for setting - * the playback sample period. 0 means default. */ - peff->dwSamplePeriod = 0; - } - - if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5)) - peff->dwStartDelay = This->effect.replay.delay * 1000; - - if (dwFlags & DIEP_TRIGGERBUTTON) { - FIXME("LinuxInput button mapping needs redoing; for now, assuming we're using an actual joystick.\n"); - peff->dwTriggerButton = DIJOFS_BUTTON(This->effect.trigger.button - BTN_JOYSTICK); - } - - if (dwFlags & DIEP_TRIGGERREPEATINTERVAL) { - peff->dwTriggerRepeatInterval = This->effect.trigger.interval * 1000; - } - - if (dwFlags & DIEP_TYPESPECIFICPARAMS) { - DWORD expectedsize = 0; - if (This->effect.type == FF_PERIODIC) { - expectedsize = sizeof(DIPERIODIC); - } else if (This->effect.type == FF_CONSTANT) { - expectedsize = sizeof(DICONSTANTFORCE); - } else if (This->effect.type == FF_SPRING - || This->effect.type == FF_FRICTION - || This->effect.type == FF_INERTIA - || This->effect.type == FF_DAMPER) { - expectedsize = sizeof(DICONDITION) * 2; - } else if (This->effect.type == FF_RAMP) { - expectedsize = sizeof(DIRAMPFORCE); - } - if (expectedsize > peff->cbTypeSpecificParams) - diErr = DIERR_MOREDATA; - peff->cbTypeSpecificParams = expectedsize; - if (diErr) - return diErr; - else { - if (This->effect.type == FF_PERIODIC) { - LPDIPERIODIC tsp = peff->lpvTypeSpecificParams; - tsp->dwMagnitude = (This->effect.u.periodic.magnitude / 33) * 10; - tsp->lOffset = (This->effect.u.periodic.offset / 33) * 10; - tsp->dwPhase = (This->effect.u.periodic.phase / 33) * 36; - tsp->dwPeriod = (This->effect.u.periodic.period * 1000); - } else if (This->effect.type == FF_CONSTANT) { - LPDICONSTANTFORCE tsp = peff->lpvTypeSpecificParams; - tsp->lMagnitude = (This->effect.u.constant.level / 33) * 10; - } else if (This->effect.type == FF_SPRING - || This->effect.type == FF_FRICTION - || This->effect.type == FF_INERTIA - || This->effect.type == FF_DAMPER) { - LPDICONDITION tsp = peff->lpvTypeSpecificParams; - int i; - for (i = 0; i < 2; ++i) { - tsp[i].lOffset = (This->effect.u.condition[i].center / 33) * 10; - tsp[i].lPositiveCoefficient = (This->effect.u.condition[i].right_coeff / 33) * 10; - tsp[i].lNegativeCoefficient = (This->effect.u.condition[i].left_coeff / 33) * 10; - tsp[i].dwPositiveSaturation = (This->effect.u.condition[i].right_saturation / 33) * 10; - tsp[i].dwNegativeSaturation = (This->effect.u.condition[i].left_saturation / 33) * 10; - tsp[i].lDeadBand = (This->effect.u.condition[i].deadband / 33) * 10; - } - } else if (This->effect.type == FF_RAMP) { - LPDIRAMPFORCE tsp = peff->lpvTypeSpecificParams; - tsp->lStart = (This->effect.u.ramp.start_level / 33) * 10; - tsp->lEnd = (This->effect.u.ramp.end_level / 33) * 10; - } - } - } - - return diErr; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Initialize( - LPDIRECTINPUTEFFECT iface, - HINSTANCE hinst, - DWORD dwVersion, - REFGUID rguid) -{ - FIXME("(this=%p,%p,%d,%s): stub!\n", - iface, hinst, dwVersion, debugstr_guid(rguid)); - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_QueryInterface( - LPDIRECTINPUTEFFECT iface, - REFIID riid, - void **ppvObject) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("(this=%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject); - - if (IsEqualGUID(&IID_IUnknown, riid) || - IsEqualGUID(&IID_IDirectInputEffect, riid)) { - LinuxInputEffectImpl_AddRef(iface); - *ppvObject = This; - return 0; - } - - TRACE("Unsupported interface!\n"); - return E_FAIL; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Start( - LPDIRECTINPUTEFFECT iface, - DWORD dwIterations, - DWORD dwFlags) -{ - struct input_event event; - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("(this=%p,%d,%d)\n", This, dwIterations, dwFlags); - - if (!(dwFlags & DIES_NODOWNLOAD)) { - /* Download the effect if necessary */ - if (This->effect.id == -1) { - HRESULT res = LinuxInputEffectImpl_Download(iface); - if (res != DI_OK) - return res; - } - } - - if (dwFlags & DIES_SOLO) { - FIXME("Solo mode requested: should be stopping all effects here!\n"); - } - - event.type = EV_FF; - event.code = This->effect.id; - event.value = min( dwIterations, INT_MAX ); - if (write(*(This->fd), &event, sizeof(event)) == -1) { - FIXME("Unable to write event. Assuming device disconnected.\n"); - return DIERR_INPUTLOST; - } - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_SetParameters( - LPDIRECTINPUTEFFECT iface, - LPCDIEFFECT peff, - DWORD dwFlags) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - DWORD type = typeFromGUID(&This->guid); - HRESULT retval = DI_OK; - - TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags); - - dump_DIEFFECT(peff, &This->guid, dwFlags); - - if (!dwFlags) - return DI_NOEFFECT; - - if (dwFlags & DIEP_AXES) { - if (!(peff->rgdwAxes)) - return DIERR_INVALIDPARAM; - - /* the linux input effect system only supports one or two axes */ - if (peff->cAxes > 2) - return DIERR_INVALIDPARAM; - else if (peff->cAxes < 1) - return DIERR_INCOMPLETEEFFECT; - This->first_axis_is_x = peff->rgdwAxes[0] == DIJOFS_X; - } - - /* some of this may look funky, but it's 'cause the linux driver and directx have - * different opinions about which way direction "0" is. directx has 0 along the x - * axis (left), linux has it along the y axis (down). */ - if (dwFlags & DIEP_DIRECTION) { - if (!(peff->rglDirection)) - return DIERR_INVALIDPARAM; - - if (peff->cAxes == 1) { - if (peff->dwFlags & DIEFF_CARTESIAN) { - if (dwFlags & DIEP_AXES) { - if (peff->rgdwAxes[0] == DIJOFS_X && peff->rglDirection[0] >= 0) - This->effect.direction = 0x4000; - else if (peff->rgdwAxes[0] == DIJOFS_X && peff->rglDirection[0] < 0) - This->effect.direction = 0xC000; - else if (peff->rgdwAxes[0] == DIJOFS_Y && peff->rglDirection[0] >= 0) - This->effect.direction = 0; - else if (peff->rgdwAxes[0] == DIJOFS_Y && peff->rglDirection[0] < 0) - This->effect.direction = 0x8000; - } - } else { - /* one-axis effects must use cartesian coords */ - return DIERR_INVALIDPARAM; - } - } - /* two axes */ - else - { - if (peff->dwFlags & DIEFF_CARTESIAN) - { - LONG x, y; - if (This->first_axis_is_x) - { - x = peff->rglDirection[0]; - y = peff->rglDirection[1]; - } - else - { - x = peff->rglDirection[1]; - y = peff->rglDirection[0]; - } - This->effect.direction = (unsigned int)((M_PI / 2 + atan2(y, x)) * 0x8000 / M_PI); - } - else - { - /* Polar and spherical are the same for 2 axes */ - /* Precision is important here, so we do double math with exact constants */ - This->effect.direction = (unsigned int)(((double)peff->rglDirection[0] / 18000) * 0x8000); - } - } - } - - if (dwFlags & DIEP_DURATION) - { - if (peff->dwDuration == INFINITE) - This->effect.replay.length = 0; /* infinite for the linux driver */ - else if(peff->dwDuration > 1000) - This->effect.replay.length = peff->dwDuration / 1000; - else - This->effect.replay.length = 1; - } - - if (dwFlags & DIEP_ENVELOPE) - { - struct ff_envelope* env; - if (This->effect.type == FF_CONSTANT) - env = &This->effect.u.constant.envelope; - else if (This->effect.type == FF_PERIODIC) - env = &This->effect.u.periodic.envelope; - else if (This->effect.type == FF_RAMP) - env = &This->effect.u.ramp.envelope; - else - env = NULL; - - /* copy the envelope if it is present and the linux effect supports it */ - if (peff->lpEnvelope && env) - { - env->attack_length = peff->lpEnvelope->dwAttackTime / 1000; - env->attack_level = (peff->lpEnvelope->dwAttackLevel / 10) * 32; - env->fade_length = peff->lpEnvelope->dwFadeTime / 1000; - env->fade_level = (peff->lpEnvelope->dwFadeLevel / 10) * 32; - } - /* if the dinput envelope is NULL we will clear the linux envelope */ - else if (env) - { - env->attack_length = 0; - env->attack_level = 0; - env->fade_length = 0; - env->fade_level = 0; - } - else if(peff->lpEnvelope) - { - if(peff->lpEnvelope->dwAttackTime || peff->lpEnvelope->dwAttackLevel || - peff->lpEnvelope->dwFadeTime || peff->lpEnvelope->dwFadeLevel) - WARN("Ignoring dinput envelope not supported in the linux effect\n"); - } - } - - /* Gain and Sample Period settings are not supported by the linux - * event system */ - if (dwFlags & DIEP_GAIN) { - This->gain = 0xFFFF * peff->dwGain / 10000; - TRACE("Effect gain requested but no effect gain functionality present.\n"); - } - - if (dwFlags & DIEP_SAMPLEPERIOD) - TRACE("Sample period requested but no sample period functionality present.\n"); - - if (dwFlags & DIEP_STARTDELAY) - if ((dwFlags & DIEP_STARTDELAY) && peff->dwSize > sizeof(DIEFFECT_DX5)) - This->effect.replay.delay = peff->dwStartDelay / 1000; - - if (dwFlags & DIEP_TRIGGERBUTTON) { - if (peff->dwTriggerButton != -1) { - FIXME("Linuxinput button mapping needs redoing, assuming we're using a joystick.\n"); - FIXME("Trigger button translation not yet implemented!\n"); - } - This->effect.trigger.button = 0; - } - - if (dwFlags & DIEP_TRIGGERREPEATINTERVAL) - This->effect.trigger.interval = peff->dwTriggerRepeatInterval / 1000; - - if (dwFlags & DIEP_TYPESPECIFICPARAMS) - { - if (!(peff->lpvTypeSpecificParams)) - return DIERR_INVALIDPARAM; - - if (type == DIEFT_PERIODIC) - { - DIPERIODIC *tsp; - if (peff->cbTypeSpecificParams != sizeof(DIPERIODIC)) - return DIERR_INVALIDPARAM; - tsp = peff->lpvTypeSpecificParams; - - This->effect.u.periodic.magnitude = (tsp->dwMagnitude / 10) * 32; - This->effect.u.periodic.offset = (tsp->lOffset / 10) * 32; - /* phase ranges from 0 - 35999 in dinput and 0 - 65535 on Linux */ - This->effect.u.periodic.phase = (tsp->dwPhase / 36) * 65; - /* dinput uses microseconds, Linux uses milliseconds */ - if (tsp->dwPeriod <= 1000) - This->effect.u.periodic.period = 1; - else - This->effect.u.periodic.period = tsp->dwPeriod / 1000; - } - else if (type == DIEFT_CONSTANTFORCE) - { - LPCDICONSTANTFORCE tsp; - if (peff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE)) - return DIERR_INVALIDPARAM; - tsp = peff->lpvTypeSpecificParams; - This->effect.u.constant.level = (max(min(tsp->lMagnitude, 10000), -10000) / 10) * 32; - } else if (type == DIEFT_RAMPFORCE) { - LPCDIRAMPFORCE tsp; - if (peff->cbTypeSpecificParams != sizeof(DIRAMPFORCE)) - return DIERR_INVALIDPARAM; - tsp = peff->lpvTypeSpecificParams; - This->effect.u.ramp.start_level = (tsp->lStart / 10) * 32; - This->effect.u.ramp.end_level = (tsp->lEnd / 10) * 32; - } - else if (type == DIEFT_CONDITION) - { - DICONDITION *tsp = peff->lpvTypeSpecificParams; - struct ff_condition_effect *cond = This->effect.u.condition; - int i, j, sources; - double factor[2]; - - if (peff->cbTypeSpecificParams == sizeof(DICONDITION)) - { - /* One condition block. This needs to be rotated to direction, - * and expanded to separate x and y conditions. Ensures 0 points right */ - double angle = ff_effect_direction_to_rad(This->effect.direction + 0xc000); - factor[0] = sin(angle); - factor[1] = -cos(angle); - sources = 1; - } - else if (peff->cbTypeSpecificParams == 2 * sizeof(DICONDITION)) - { - /* Direct parameter copy without changes */ - factor[0] = factor[1] = 1; - sources = 2; - } - else - return DIERR_INVALIDPARAM; - - for (i = j = 0; i < 2; ++i) - { - cond[i].center = (int)(factor[i] * (tsp[j].lOffset / 10) * 32); - cond[i].right_coeff = (int)(factor[i] * (tsp[j].lPositiveCoefficient / 10) * 32); - cond[i].left_coeff = (int)(factor[i] * (tsp[j].lNegativeCoefficient / 10) * 32); - cond[i].right_saturation = (int)(factor[i] * (tsp[j].dwPositiveSaturation / 10) * 65); - cond[i].left_saturation = (int)(factor[i] * (tsp[j].dwNegativeSaturation / 10) * 65); - cond[i].deadband = (int)(factor[i] * (tsp[j].lDeadBand / 10) * 32); - if (sources == 2) - j++; - } - } - else - { - FIXME("Custom force types are not supported\n"); - return DIERR_INVALIDPARAM; - } - } - - if (!(dwFlags & DIEP_NODOWNLOAD)) - retval = LinuxInputEffectImpl_Download(iface); - if (retval != DI_OK) - return DI_DOWNLOADSKIPPED; - - if (dwFlags & DIEP_NORESTART) - TRACE("DIEP_NORESTART: not handled (we have no control of that).\n"); - - if (dwFlags & DIEP_START) - retval = LinuxInputEffectImpl_Start(iface, 1, 0); - if (retval != DI_OK) - return retval; - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Stop( - LPDIRECTINPUTEFFECT iface) -{ - struct input_event event; - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("(this=%p)\n", This); - - event.type = EV_FF; - event.code = This->effect.id; - event.value = 0; - /* we don't care about the success or failure of this call */ - write(*(This->fd), &event, sizeof(event)); - - return DI_OK; -} - -static HRESULT WINAPI LinuxInputEffectImpl_Unload( - LPDIRECTINPUTEFFECT iface) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("(this=%p)\n", This); - - /* Erase the downloaded effect */ - if (ioctl(*(This->fd), EVIOCRMFF, This->effect.id) == -1) - return DIERR_INVALIDPARAM; - - /* Mark the effect as deallocated */ - This->effect.id = -1; - - return DI_OK; -} - -static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface) -{ - LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface); - ULONG ref = InterlockedDecrement(&(This->ref)); - - TRACE( "(%p) ref %d\n", This, ref ); - - if (ref == 0) - { - LinuxInputEffectImpl_Stop(iface); - LinuxInputEffectImpl_Unload(iface); - list_remove(This->entry); - HeapFree(GetProcessHeap(), 0, LIST_ENTRY(This->entry, effect_list_item, entry)); - HeapFree(GetProcessHeap(), 0, This); - } - return ref; -} - -/****************************************************************************** - * LinuxInputEffect - */ - -DECLSPEC_HIDDEN HRESULT linuxinput_create_effect( - int* fd, - REFGUID rguid, - struct list *parent_list_entry, - LPDIRECTINPUTEFFECT* peff) -{ - LinuxInputEffectImpl* newEffect = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, sizeof(LinuxInputEffectImpl)); - DWORD type = typeFromGUID(rguid); - - newEffect->IDirectInputEffect_iface.lpVtbl = &LinuxInputEffectVtbl; - newEffect->ref = 1; - newEffect->guid = *rguid; - newEffect->fd = fd; - newEffect->gain = 0xFFFF; - - /* set the type. this cannot be changed over the effect's life. */ - switch (type) { - case DIEFT_PERIODIC: - newEffect->effect.type = FF_PERIODIC; - if (IsEqualGUID(rguid, &GUID_Sine)) { - newEffect->effect.u.periodic.waveform = FF_SINE; - } else if (IsEqualGUID(rguid, &GUID_Triangle)) { - newEffect->effect.u.periodic.waveform = FF_TRIANGLE; - } else if (IsEqualGUID(rguid, &GUID_Square)) { - newEffect->effect.u.periodic.waveform = FF_SQUARE; - } else if (IsEqualGUID(rguid, &GUID_SawtoothUp)) { - newEffect->effect.u.periodic.waveform = FF_SAW_UP; - } else if (IsEqualGUID(rguid, &GUID_SawtoothDown)) { - newEffect->effect.u.periodic.waveform = FF_SAW_DOWN; - } - break; - case DIEFT_CONSTANTFORCE: - newEffect->effect.type = FF_CONSTANT; - break; - case DIEFT_RAMPFORCE: - newEffect->effect.type = FF_RAMP; - break; - case DIEFT_CONDITION: - if (IsEqualGUID(rguid, &GUID_Spring)) { - newEffect->effect.type = FF_SPRING; - } else if (IsEqualGUID(rguid, &GUID_Friction)) { - newEffect->effect.type = FF_FRICTION; - } else if (IsEqualGUID(rguid, &GUID_Inertia)) { - newEffect->effect.type = FF_INERTIA; - } else if (IsEqualGUID(rguid, &GUID_Damper)) { - newEffect->effect.type = FF_DAMPER; - } - break; - case DIEFT_CUSTOMFORCE: - FIXME("Custom forces are not supported.\n"); - HeapFree(GetProcessHeap(), 0, newEffect); - return DIERR_INVALIDPARAM; - default: - FIXME("Unknown force type 0x%x.\n", type); - HeapFree(GetProcessHeap(), 0, newEffect); - return DIERR_INVALIDPARAM; - } - - /* mark as non-uploaded */ - newEffect->effect.id = -1; - - newEffect->entry = parent_list_entry; - - *peff = &newEffect->IDirectInputEffect_iface; - - TRACE("Creating linux input system effect (%p) with guid %s\n", - *peff, _dump_dinput_GUID(rguid)); - - return DI_OK; -} - -DECLSPEC_HIDDEN HRESULT linuxinput_get_info_W( - int fd, - REFGUID rguid, - LPDIEFFECTINFOW info) -{ - DWORD type = typeFromGUID(rguid); - - TRACE("(%d, %s, %p) type=%d\n", fd, _dump_dinput_GUID(rguid), info, type); - - if (!info) return E_POINTER; - - if (info->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM; - - info->guid = *rguid; - - info->dwEffType = type; - /* the event device API does not support querying for all these things - * therefore we assume that we have support for them - * that's not as dangerous as it sounds, since drivers are allowed to - * ignore parameters they claim to support anyway */ - info->dwEffType |= DIEFT_DEADBAND | DIEFT_FFATTACK | DIEFT_FFFADE - | DIEFT_POSNEGCOEFFICIENTS | DIEFT_POSNEGSATURATION - | DIEFT_SATURATION | DIEFT_STARTDELAY; - - /* again, assume we have support for everything */ - info->dwStaticParams = DIEP_ALLPARAMS; - info->dwDynamicParams = info->dwStaticParams; - - /* yes, this is windows behavior (print the GUID_Name for name) */ - MultiByteToWideChar(CP_ACP, 0, _dump_dinput_GUID(rguid), -1, - info->tszName, MAX_PATH); - - return DI_OK; -} - -static const IDirectInputEffectVtbl LinuxInputEffectVtbl = { - LinuxInputEffectImpl_QueryInterface, - LinuxInputEffectImpl_AddRef, - LinuxInputEffectImpl_Release, - LinuxInputEffectImpl_Initialize, - LinuxInputEffectImpl_GetEffectGuid, - LinuxInputEffectImpl_GetParameters, - LinuxInputEffectImpl_SetParameters, - LinuxInputEffectImpl_Start, - LinuxInputEffectImpl_Stop, - LinuxInputEffectImpl_GetEffectStatus, - LinuxInputEffectImpl_Download, - LinuxInputEffectImpl_Unload, - LinuxInputEffectImpl_Escape -}; - -#endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */ diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c deleted file mode 100644 index afebaa022b7..00000000000 --- a/dlls/dinput/joystick.c +++ /dev/null @@ -1,962 +0,0 @@ -/* DirectInput Generic Joystick device - * - * Copyright 1998 Marcus Meissner - * Copyright 1998,1999 Lionel Ulmer - * Copyright 2000-2001 TransGaming Technologies Inc. - * Copyright 2009 Aric Stewart, 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 - */ - -/* - * To Do: - * dead zone - * force feedback - */ - -#include <stdio.h> - -#include "joystick_private.h" -#include "wine/debug.h" -#include "winreg.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dinput); - -#define VID_MICROSOFT 0x045e - -static const WORD PID_XBOX_CONTROLLERS[] = { - 0x0202, /* Xbox Controller */ - 0x0285, /* Xbox Controller S */ - 0x0289, /* Xbox Controller S */ - 0x028e, /* Xbox360 Controller */ - 0x028f, /* Xbox360 Wireless Controller */ - 0x02d1, /* Xbox One Controller */ - 0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */ - 0x02e0, /* Xbox One X Controller */ - 0x02e3, /* Xbox One Elite Controller */ - 0x02e6, /* Wireless XBox Controller Dongle */ - 0x02ea, /* Xbox One S Controller */ - 0x02fd, /* Xbox One S Controller (Firmware 2017) */ - 0x0719, /* Xbox 360 Wireless Adapter */ -}; - -static inline JoystickGenericImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) -{ - return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), JoystickGenericImpl, base); -} - -DWORD typeFromGUID(REFGUID guid) -{ - if (IsEqualGUID(guid, &GUID_ConstantForce)) { - return DIEFT_CONSTANTFORCE; - } else if (IsEqualGUID(guid, &GUID_Square) - || IsEqualGUID(guid, &GUID_Sine) - || IsEqualGUID(guid, &GUID_Triangle) - || IsEqualGUID(guid, &GUID_SawtoothUp) - || IsEqualGUID(guid, &GUID_SawtoothDown)) { - return DIEFT_PERIODIC; - } else if (IsEqualGUID(guid, &GUID_RampForce)) { - return DIEFT_RAMPFORCE; - } else if (IsEqualGUID(guid, &GUID_Spring) - || IsEqualGUID(guid, &GUID_Damper) - || IsEqualGUID(guid, &GUID_Inertia) - || IsEqualGUID(guid, &GUID_Friction)) { - return DIEFT_CONDITION; - } else if (IsEqualGUID(guid, &GUID_CustomForce)) { - return DIEFT_CUSTOMFORCE; - } else { - WARN("GUID (%s) is not a known force type\n", _dump_dinput_GUID(guid)); - return 0; - } -} - -DWORD get_device_type(DWORD version, BOOL is_joystick) -{ - if (is_joystick) - return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : - DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - - return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) : - DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8); -} - -static void _dump_DIEFFECT_flags(DWORD dwFlags) -{ - if (TRACE_ON(dinput)) { - unsigned int i; - static const struct { - DWORD mask; - const char *name; - } flags[] = { -#define FE(x) { x, #x} - FE(DIEFF_CARTESIAN), - FE(DIEFF_OBJECTIDS), - FE(DIEFF_OBJECTOFFSETS), - FE(DIEFF_POLAR), - FE(DIEFF_SPHERICAL) -#undef FE - }; - for (i = 0; i < ARRAY_SIZE(flags); i++) - if (flags[i].mask & dwFlags) - TRACE("%s ", flags[i].name); - TRACE("\n"); - } -} - -static void _dump_DIENVELOPE(LPCDIENVELOPE env) -{ - if (env->dwSize != sizeof(DIENVELOPE)) { - WARN("Non-standard DIENVELOPE structure size %d.\n", env->dwSize); - } - TRACE("Envelope has attack (level: %d time: %d), fade (level: %d time: %d)\n", - env->dwAttackLevel, env->dwAttackTime, env->dwFadeLevel, env->dwFadeTime); -} - -static void _dump_DICONSTANTFORCE(LPCDICONSTANTFORCE frc) -{ - TRACE("Constant force has magnitude %d\n", frc->lMagnitude); -} - -static void _dump_DIPERIODIC(LPCDIPERIODIC frc) -{ - TRACE("Periodic force has magnitude %d, offset %d, phase %d, period %d\n", - frc->dwMagnitude, frc->lOffset, frc->dwPhase, frc->dwPeriod); -} - -static void _dump_DIRAMPFORCE(LPCDIRAMPFORCE frc) -{ - TRACE("Ramp force has start %d, end %d\n", - frc->lStart, frc->lEnd); -} - -static void _dump_DICONDITION(LPCDICONDITION frc) -{ - TRACE("Condition has offset %d, pos/neg coefficients %d and %d, pos/neg saturations %d and %d, deadband %d\n", - frc->lOffset, frc->lPositiveCoefficient, frc->lNegativeCoefficient, - frc->dwPositiveSaturation, frc->dwNegativeSaturation, frc->lDeadBand); -} - -static void _dump_DICUSTOMFORCE(LPCDICUSTOMFORCE frc) -{ - unsigned int i; - TRACE("Custom force uses %d channels, sample period %d. Has %d samples at %p.\n", - frc->cChannels, frc->dwSamplePeriod, frc->cSamples, frc->rglForceData); - if (frc->cSamples % frc->cChannels != 0) - WARN("Custom force has a non-integral samples-per-channel count!\n"); - if (TRACE_ON(dinput)) { - TRACE("Custom force data (time aligned, axes in order):\n"); - for (i = 1; i <= frc->cSamples; ++i) { - TRACE("%d ", frc->rglForceData[i]); - if (i % frc->cChannels == 0) - TRACE("\n"); - } - } -} - -void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) -{ - DWORD type = typeFromGUID(guid); - unsigned int i; - - TRACE("Dumping DIEFFECT structure:\n"); - TRACE(" - dwSize: %d\n", eff->dwSize); - if ((eff->dwSize != sizeof(DIEFFECT)) && (eff->dwSize != sizeof(DIEFFECT_DX5))) { - WARN("Non-standard DIEFFECT structure size %d\n", eff->dwSize); - } - TRACE(" - dwFlags: %d\n", eff->dwFlags); - TRACE(" "); - _dump_DIEFFECT_flags(eff->dwFlags); - TRACE(" - dwDuration: %d\n", eff->dwDuration); - TRACE(" - dwGain: %d\n", eff->dwGain); - - if (eff->dwGain > 10000) - WARN("dwGain is out of range (>10,000)\n"); - - TRACE(" - dwTriggerButton: %d\n", eff->dwTriggerButton); - TRACE(" - dwTriggerRepeatInterval: %d\n", eff->dwTriggerRepeatInterval); - TRACE(" - rglDirection: %p\n", eff->rglDirection); - if (dwFlags & DIEP_DIRECTION && eff->rglDirection) { - TRACE(" "); - for (i = 0; i < eff->cAxes; ++i) - TRACE("%d ", eff->rglDirection[i]); - TRACE("\n"); - } - TRACE(" - cbTypeSpecificParams: %d\n", eff->cbTypeSpecificParams); - TRACE(" - lpvTypeSpecificParams: %p\n", eff->lpvTypeSpecificParams); - - /* Only trace some members if dwFlags indicates they have data */ - if (dwFlags & DIEP_AXES) { - TRACE(" - cAxes: %d\n", eff->cAxes); - TRACE(" - rgdwAxes: %p\n", eff->rgdwAxes); - - if (TRACE_ON(dinput) && eff->rgdwAxes) { - TRACE(" "); - for (i = 0; i < eff->cAxes; ++i) - TRACE("%d ", eff->rgdwAxes[i]); - TRACE("\n"); - } - } - - if (dwFlags & DIEP_ENVELOPE) { - TRACE(" - lpEnvelope: %p\n", eff->lpEnvelope); - if (eff->lpEnvelope != NULL) - _dump_DIENVELOPE(eff->lpEnvelope); - } - - if (eff->dwSize > sizeof(DIEFFECT_DX5)) - TRACE(" - dwStartDelay: %d\n", eff->dwStartDelay); - - if (type == DIEFT_CONSTANTFORCE) { - if (eff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE)) { - WARN("Effect claims to be a constant force but the type-specific params are the wrong size!\n"); - } else if (!eff->lpvTypeSpecificParams) { - WARN("Size of type-specific params is correct but pointer is NULL!\n"); - } else { - _dump_DICONSTANTFORCE(eff->lpvTypeSpecificParams); - } - } else if (type == DIEFT_PERIODIC) { - if (eff->cbTypeSpecificParams != sizeof(DIPERIODIC)) { - WARN("Effect claims to be a periodic force but the type-specific params are the wrong size!\n"); - } else if (!eff->lpvTypeSpecificParams) { - WARN("Size of type-specific params is correct but pointer is NULL!\n"); - } else { - _dump_DIPERIODIC(eff->lpvTypeSpecificParams); - } - } else if (type == DIEFT_RAMPFORCE) { - if (eff->cbTypeSpecificParams != sizeof(DIRAMPFORCE)) { - WARN("Effect claims to be a ramp force but the type-specific params are the wrong size!\n"); - } else if (!eff->lpvTypeSpecificParams) { - WARN("Size of type-specific params is correct but pointer is NULL!\n"); - } else { - _dump_DIRAMPFORCE(eff->lpvTypeSpecificParams); - } - } else if (type == DIEFT_CONDITION) { - if (eff->cbTypeSpecificParams == sizeof(DICONDITION) && eff->lpvTypeSpecificParams) { - _dump_DICONDITION(eff->lpvTypeSpecificParams); - } else if (eff->cbTypeSpecificParams == 2 * sizeof(DICONDITION) && eff->lpvTypeSpecificParams) { - DICONDITION *condition = eff->lpvTypeSpecificParams; - _dump_DICONDITION(&condition[0]); - _dump_DICONDITION(&condition[1]); - } else { - WARN("Effect claims to be a condition but the type-specific params are the wrong size or NULL!\n"); - } - } else if (type == DIEFT_CUSTOMFORCE) { - if (eff->cbTypeSpecificParams != sizeof(DICUSTOMFORCE)) { - WARN("Effect claims to be a custom force but the type-specific params are the wrong size!\n"); - } else if (!eff->lpvTypeSpecificParams) { - WARN("Size of type-specific params is correct but pointer is NULL!\n"); - } else { - _dump_DICUSTOMFORCE(eff->lpvTypeSpecificParams); - } - } -} - -BOOL device_disabled_registry(const char* name) -{ - DIDEVICEINSTANCEW instance; - - MultiByteToWideChar( CP_ACP, 0, name, -1, instance.tszInstanceName, MAX_PATH ); - return device_instance_is_disabled( &instance, NULL ); -} - -BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) -{ - int i; - - if (vid == VID_MICROSOFT) - { - for (i = 0; i < ARRAY_SIZE(PID_XBOX_CONTROLLERS); i++) - if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE; - } - - return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14); -} - -/****************************************************************************** - * SetProperty : change input device properties - */ -HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - DWORD i; - ObjProps remap_props; - - TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph); - - if (ph == NULL) { - WARN("invalid parameter: ph == NULL\n"); - return DIERR_INVALIDPARAM; - } - - if (TRACE_ON(dinput)) - _dump_DIPROPHEADER(ph); - - if (IS_DIPROP(rguid)) { - switch (LOWORD(rguid)) { - case (DWORD_PTR)DIPROP_RANGE: { - LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph; - if (ph->dwHow == DIPH_DEVICE) { - - /* Many games poll the joystick immediately after setting the range - * for calibration purposes, so the old values need to be remapped - * to the new range before it does so */ - - TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax); - for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) { - - remap_props.lDevMin = This->props[i].lMin; - remap_props.lDevMax = This->props[i].lMax; - - remap_props.lDeadZone = This->props[i].lDeadZone; - remap_props.lSaturation = This->props[i].lSaturation; - - remap_props.lMin = pr->lMin; - remap_props.lMax = pr->lMax; - - switch (This->base.data_format.wine_df->rgodf[i].dwOfs) { - case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; - case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; - case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; - case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; - case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; - case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; - case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; - case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; - default: break; - } - - This->props[i].lMin = pr->lMin; - This->props[i].lMax = pr->lMax; - } - } else { - int obj = find_property(&This->base.data_format, ph); - - TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj); - if (obj >= 0) { - - remap_props.lDevMin = This->props[obj].lMin; - remap_props.lDevMax = This->props[obj].lMax; - - remap_props.lDeadZone = This->props[obj].lDeadZone; - remap_props.lSaturation = This->props[obj].lSaturation; - - remap_props.lMin = pr->lMin; - remap_props.lMax = pr->lMax; - - switch (This->base.data_format.wine_df->rgodf[obj].dwOfs) { - case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break; - case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break; - case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break; - case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break; - case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break; - case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break; - case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break; - case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break; - default: break; - } - - This->props[obj].lMin = pr->lMin; - This->props[obj].lMax = pr->lMax; - return DI_OK; - } - } - break; - } - case (DWORD_PTR)DIPROP_DEADZONE: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - if (ph->dwHow == DIPH_DEVICE) { - TRACE("deadzone(%d) all\n", pd->dwData); - for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) - This->props[i].lDeadZone = pd->dwData; - } else { - int obj = find_property(&This->base.data_format, ph); - - TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj); - if (obj >= 0) { - This->props[obj].lDeadZone = pd->dwData; - return DI_OK; - } - } - break; - } - case (DWORD_PTR)DIPROP_SATURATION: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - if (ph->dwHow == DIPH_DEVICE) { - TRACE("saturation(%d) all\n", pd->dwData); - for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) - This->props[i].lSaturation = pd->dwData; - } else { - int obj = find_property(&This->base.data_format, ph); - - TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); - if (obj >= 0) { - This->props[obj].lSaturation = pd->dwData; - return DI_OK; - } - } - break; - } - case (DWORD_PTR)DIPROP_CALIBRATIONMODE: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData); - break; - } - default: - return IDirectInputDevice2WImpl_SetProperty(iface, rguid, ph); - } - } - - return DI_OK; -} - -#define DEBUG_TYPE(x) case (x): str = #x; break -void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) -{ - int type = GET_DIDEVICE_TYPE(lpDIDevCaps->dwDevType); - const char *str, *hid = ""; - TRACE("dwSize: %d\n", lpDIDevCaps->dwSize); - TRACE("dwFlags: %08x\n", lpDIDevCaps->dwFlags); - switch(type) - { - /* Direct X <= 7 definitions */ - DEBUG_TYPE(DIDEVTYPE_DEVICE); - DEBUG_TYPE(DIDEVTYPE_MOUSE); - DEBUG_TYPE(DIDEVTYPE_KEYBOARD); - DEBUG_TYPE(DIDEVTYPE_JOYSTICK); - /* Direct X >= 8 definitions */ - DEBUG_TYPE(DI8DEVTYPE_DEVICE); - DEBUG_TYPE(DI8DEVTYPE_MOUSE); - DEBUG_TYPE(DI8DEVTYPE_KEYBOARD); - DEBUG_TYPE(DI8DEVTYPE_JOYSTICK); - DEBUG_TYPE(DI8DEVTYPE_GAMEPAD); - DEBUG_TYPE(DI8DEVTYPE_DRIVING); - DEBUG_TYPE(DI8DEVTYPE_FLIGHT); - DEBUG_TYPE(DI8DEVTYPE_1STPERSON); - DEBUG_TYPE(DI8DEVTYPE_DEVICECTRL); - DEBUG_TYPE(DI8DEVTYPE_SCREENPOINTER); - DEBUG_TYPE(DI8DEVTYPE_REMOTE); - DEBUG_TYPE(DI8DEVTYPE_SUPPLEMENTAL); - default: str = "UNKNOWN"; - } - - if (lpDIDevCaps->dwDevType & DIDEVTYPE_HID) - hid = " (HID)"; - - TRACE("dwDevType: %08x %s%s\n", lpDIDevCaps->dwDevType, str, hid); - TRACE("dwAxes: %d\n", lpDIDevCaps->dwAxes); - TRACE("dwButtons: %d\n", lpDIDevCaps->dwButtons); - TRACE("dwPOVs: %d\n", lpDIDevCaps->dwPOVs); - if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) { - TRACE("dwFFSamplePeriod: %d\n", lpDIDevCaps->dwFFSamplePeriod); - TRACE("dwFFMinTimeResolution: %d\n", lpDIDevCaps->dwFFMinTimeResolution); - TRACE("dwFirmwareRevision: %d\n", lpDIDevCaps->dwFirmwareRevision); - TRACE("dwHardwareRevision: %d\n", lpDIDevCaps->dwHardwareRevision); - TRACE("dwFFDriverVersion: %d\n", lpDIDevCaps->dwFFDriverVersion); - } -} -#undef DEBUG_TYPE - -HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - int size; - - TRACE("%p->(%p)\n",This,lpDIDevCaps); - - if (lpDIDevCaps == NULL) { - WARN("invalid pointer\n"); - return E_POINTER; - } - - size = lpDIDevCaps->dwSize; - - if (!(size == sizeof(DIDEVCAPS) || size == sizeof(DIDEVCAPS_DX3))) { - WARN("invalid parameter\n"); - return DIERR_INVALIDPARAM; - } - - CopyMemory(lpDIDevCaps, &This->devcaps, size); - lpDIDevCaps->dwSize = size; - - if (TRACE_ON(dinput)) - _dump_DIDEVCAPS(lpDIDevCaps); - - return DI_OK; -} - - -ULONG WINAPI JoystickWGenericImpl_Release(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - void *axis_map = This->axis_map; - ULONG res = IDirectInputDevice2WImpl_Release(iface); - if (!res) HeapFree(GetProcessHeap(), 0, axis_map); - return res; -} - - -/****************************************************************************** - * GetObjectInfo : get object info - */ -HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, - LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) -{ - static const WCHAR axisW[] = {'A','x','i','s',' ','%','d',0}; - static const WCHAR povW[] = {'P','O','V',' ','%','d',0}; - static const WCHAR buttonW[] = {'B','u','t','t','o','n',' ','%','d',0}; - HRESULT res; - - res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); - if (res != DI_OK) return res; - - if (pdidoi->dwType & DIDFT_AXIS) { - sprintfW(pdidoi->tszName, axisW, DIDFT_GETINSTANCE(pdidoi->dwType)); - pdidoi->dwFlags |= DIDOI_ASPECTPOSITION; - } else if (pdidoi->dwType & DIDFT_POV) - sprintfW(pdidoi->tszName, povW, DIDFT_GETINSTANCE(pdidoi->dwType)); - else if (pdidoi->dwType & DIDFT_BUTTON) - sprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType)); - - _dump_OBJECTINSTANCEW(pdidoi); - return res; -} - -/****************************************************************************** - * GetProperty : get input device properties - */ -HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p,%s,%p)\n", This, debugstr_guid(rguid), pdiph); - - if (TRACE_ON(dinput)) - _dump_DIPROPHEADER(pdiph); - - if (IS_DIPROP(rguid)) { - switch (LOWORD(rguid)) { - case (DWORD_PTR) DIPROP_RANGE: { - LPDIPROPRANGE pr = (LPDIPROPRANGE)pdiph; - int obj = find_property(&This->base.data_format, pdiph); - - /* The app is querying the current range of the axis - * return the lMin and lMax values */ - if (obj >= 0) { - pr->lMin = This->props[obj].lMin; - pr->lMax = This->props[obj].lMax; - TRACE("range(%d, %d) obj=%d\n", pr->lMin, pr->lMax, obj); - return DI_OK; - } - break; - } - case (DWORD_PTR) DIPROP_DEADZONE: { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - int obj = find_property(&This->base.data_format, pdiph); - - if (obj >= 0) { - pd->dwData = This->props[obj].lDeadZone; - TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj); - return DI_OK; - } - break; - } - case (DWORD_PTR) DIPROP_SATURATION: { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - int obj = find_property(&This->base.data_format, pdiph); - - if (obj >= 0) { - pd->dwData = This->props[obj].lSaturation; - TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); - return DI_OK; - } - break; - } - case (DWORD_PTR) DIPROP_PRODUCTNAME: - case (DWORD_PTR) DIPROP_INSTANCENAME: { - DIPROPSTRING *ps = (DIPROPSTRING*) pdiph; - DIDEVICEINSTANCEW didev; - - didev.dwSize = sizeof(didev); - - IDirectInputDevice_GetDeviceInfo(iface, &didev); - if (LOWORD(rguid) == (DWORD_PTR) DIPROP_PRODUCTNAME) - lstrcpynW(ps->wsz, didev.tszProductName, MAX_PATH); - else - lstrcpynW(ps->wsz, didev.tszInstanceName, MAX_PATH); - - return DI_OK; - } - default: - return IDirectInputDevice2WImpl_GetProperty(iface, rguid, pdiph); - } - } - - return DI_OK; -} - -/****************************************************************************** - * GetDeviceInfo : get information about a device's identity - */ -HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo( - LPDIRECTINPUTDEVICE8W iface, - LPDIDEVICEINSTANCEW pdidi) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - CHAR buffer[MAX_PATH]; - DIPROPDWORD pd; - DWORD index = 0; - - TRACE("(%p,%p)\n", iface, pdidi); - - if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) && - (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) { - WARN("invalid parameter: pdidi->dwSize = %d\n", pdidi->dwSize); - return DIERR_INVALIDPARAM; - } - - /* Try to get joystick index */ - pd.diph.dwSize = sizeof(pd); - pd.diph.dwHeaderSize = sizeof(pd.diph); - pd.diph.dwObj = 0; - pd.diph.dwHow = DIPH_DEVICE; - if (SUCCEEDED(IDirectInputDevice2_GetProperty(iface, DIPROP_JOYSTICKID, &pd.diph))) - index = pd.dwData; - - /* Return joystick */ - pdidi->guidInstance = This->base.guid; - pdidi->guidProduct = This->guidProduct; - /* we only support traditional joysticks for now */ - pdidi->dwDevType = This->devcaps.dwDevType; - snprintf(buffer, sizeof(buffer), "Joystick %d", index); - MultiByteToWideChar(CP_ACP, 0, buffer, -1, pdidi->tszInstanceName, MAX_PATH); - MultiByteToWideChar(CP_ACP, 0, This->name, -1, pdidi->tszProductName, MAX_PATH); - if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3W)) { - pdidi->guidFFDriver = GUID_NULL; - pdidi->wUsagePage = 0; - pdidi->wUsage = 0; - } - - return DI_OK; -} - -HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p)\n",This); - - if (!This->base.acquired) { - WARN("not acquired\n"); - return DIERR_NOTACQUIRED; - } - - This->joy_polldev( iface ); - return DI_OK; -} - -/****************************************************************************** - * GetDeviceState : returns the "state" of the joystick. - * - */ -HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p,0x%08x,%p)\n", This, len, ptr); - - if (!This->base.acquired) { - WARN("not acquired\n"); - return DIERR_NOTACQUIRED; - } - - /* update joystick state */ - This->joy_polldev( iface ); - - /* convert and copy data to user supplied buffer */ - fill_DataFormat(ptr, len, &This->js, &This->base.data_format); - - return DI_OK; -} - -HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, - LPDIACTIONFORMATW lpdiaf, - LPCWSTR lpszUserName, - DWORD dwFlags) -{ - static const DWORD object_types[] = { DIDFT_AXIS, DIDFT_BUTTON }; - static const DWORD type_map[] = { DIDFT_RELAXIS, DIDFT_PSHBUTTON }; - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - unsigned int i, j; - BOOL has_actions = FALSE; - - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags); - - for (i=0; i < lpdiaf->dwNumActions; i++) - { - DWORD inst = (0x000000ff & (lpdiaf->rgoAction[i].dwSemantic)) - 1; - DWORD type = 0x000000ff & (lpdiaf->rgoAction[i].dwSemantic >> 8); - DWORD genre = 0xff000000 & lpdiaf->rgoAction[i].dwSemantic; - - /* Don't touch a user configured action */ - if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue; - - /* Only consider actions of the right genre */ - if (lpdiaf->dwGenre != genre && genre != DIGENRE_ANY) continue; - - for (j = 0; j < ARRAY_SIZE(object_types); j++) - { - if (type & object_types[j]) - { - /* Ensure that the object exists */ - LPDIOBJECTDATAFORMAT odf = dataformat_to_odf_by_type(This->base.data_format.wine_df, inst, object_types[j]); - - if (odf != NULL) - { - lpdiaf->rgoAction[i].dwObjID = type_map[j] | (0x0000ff00 & (inst << 8)); - lpdiaf->rgoAction[i].guidInstance = This->base.guid; - lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT; - - has_actions = TRUE; - - /* No need to try other types if the action was already mapped */ - break; - } - } - } - } - - if (!has_actions) return DI_NOEFFECT; - - return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags); -} - -HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, - LPDIACTIONFORMATW lpdiaf, - LPCWSTR lpszUserName, - DWORD dwFlags) -{ - JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface); - - FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags); - - return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, This->base.data_format.wine_df); -} - -/* - * This maps the read value (from the input event) to a value in the - * 'wanted' range. - * Notes: - * Dead zone is in % multiplied by a 100 (range 0..10000) - */ -LONG joystick_map_axis(ObjProps *props, int val) -{ - LONG ret; - LONG dead_zone = MulDiv( props->lDeadZone, props->lDevMax - props->lDevMin, 10000 ); - LONG dev_range = props->lDevMax - props->lDevMin - dead_zone; - - /* Center input */ - val -= (props->lDevMin + props->lDevMax) / 2; - - /* Remove dead zone */ - if (abs( val ) <= dead_zone / 2) - val = 0; - else - val = val < 0 ? val + dead_zone / 2 : val - dead_zone / 2; - - /* Scale and map the value from the device range into the required range */ - ret = MulDiv( val, props->lMax - props->lMin, dev_range ) + - (props->lMin + props->lMax) / 2; - - /* Clamp in case or rounding errors */ - if (ret > props->lMax) ret = props->lMax; - else if (ret < props->lMin) ret = props->lMin; - - TRACE( "(%d <%d> %d) -> (%d <%d> %d): val=%d ret=%d\n", - props->lDevMin, dead_zone, props->lDevMax, - props->lMin, props->lDeadZone, props->lMax, - val, ret ); - - return ret; -} - -/* - * Maps POV x & y event values to a DX "clock" position: - * 0 - * 31500 4500 - * 27000 -1 9000 - * 22500 13500 - * 18000 - */ -DWORD joystick_map_pov(const POINTL *p) -{ - if (p->x > 0) - return p->y < 0 ? 4500 : !p->y ? 9000 : 13500; - else if (p->x < 0) - return p->y < 0 ? 31500 : !p->y ? 27000 : 22500; - else - return p->y < 0 ? 0 : !p->y ? -1 : 18000; -} - -static DWORD get_config_key_a( HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size ) -{ - if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0; - - if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0; - - return ERROR_FILE_NOT_FOUND; -} - -/* - * Setup the dinput options. - */ - -HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map) -{ - char buffer[MAX_PATH+16]; - HKEY hkey, appkey; - int tokens = 0; - int axis = 0; - int pov = 0; - - get_app_key(&hkey, &appkey); - - /* get options */ - - if (!get_config_key_a( hkey, appkey, "DefaultDeadZone", buffer, sizeof(buffer) )) - { - This->deadzone = atoi(buffer); - TRACE("setting default deadzone to: "%s" %d\n", buffer, This->deadzone); - } - - This->axis_map = HeapAlloc(GetProcessHeap(), 0, This->device_axis_count * sizeof(int)); - if (!This->axis_map) return DIERR_OUTOFMEMORY; - - if (!get_config_key_a( hkey, appkey, This->name, buffer, sizeof(buffer) )) - { - static const char *axis_names[] = {"X", "Y", "Z", "Rx", "Ry", "Rz", - "Slider1", "Slider2", - "POV1", "POV2", "POV3", "POV4"}; - const char *delim = ","; - char * ptr; - TRACE(""%s" = "%s"\n", This->name, buffer); - - if ((ptr = strtok(buffer, delim)) != NULL) - { - do - { - int i; - - for (i = 0; i < ARRAY_SIZE(axis_names); i++) - { - if (!strcmp(ptr, axis_names[i])) - { - if (!strncmp(ptr, "POV", 3)) - { - if (pov >= 4) - { - WARN("Only 4 POVs supported - ignoring extra\n"); - i = -1; - } - else - { - /* Pov takes two axes */ - This->axis_map[tokens++] = i; - pov++; - } - } - else - { - if (axis >= 8) - { - FIXME("Only 8 Axes supported - ignoring extra\n"); - i = -1; - } - else - axis++; - } - break; - } - } - - if (i == ARRAY_SIZE(axis_names)) - { - ERR("invalid joystick axis type: "%s"\n", ptr); - i = -1; - } - - This->axis_map[tokens] = i; - tokens++; - } while ((ptr = strtok(NULL, delim)) != NULL); - - if (tokens != This->device_axis_count) - { - ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n", - This->device_axis_count, axis, pov, tokens); - while (tokens < This->device_axis_count) - { - This->axis_map[tokens] = -1; - tokens++; - } - } - } - } - else - { - int i; - - if (default_axis_map) - { - /* Use default mapping from the driver */ - for (i = 0; i < This->device_axis_count; i++) - { - This->axis_map[i] = default_axis_map[i]; - tokens = default_axis_map[i]; - if (tokens < 0) - continue; - if (tokens < 8) - axis++; - else if (tokens < 15) - { - i++; - pov++; - This->axis_map[i] = default_axis_map[i]; - } - } - } - else - { - /* No config - set default mapping. */ - for (i = 0; i < This->device_axis_count; i++) - { - if (i < 8) - This->axis_map[i] = axis++; - else if (i < 15) - { - This->axis_map[i++] = 8 + pov; - This->axis_map[i ] = 8 + pov++; - } - else - This->axis_map[i] = -1; - } - } - } - This->devcaps.dwAxes = axis; - This->devcaps.dwPOVs = pov; - - if (appkey) RegCloseKey(appkey); - if (hkey) RegCloseKey(hkey); - - return DI_OK; -} diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 63193554405..9af4ef8ba3f 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -37,16 +37,16 @@ #include "dinput.h" #include "setupapi.h"
-#include "wine/debug.h" -#include "wine/hid.h" - #include "dinput_private.h" #include "device_private.h" -#include "joystick_private.h"
#include "initguid.h" #include "devpkey.h"
+#include "wine/unicode.h" +#include "wine/debug.h" +#include "wine/hid.h" + WINE_DEFAULT_DEBUG_CHANNEL(dinput);
DEFINE_GUID( GUID_DEVINTERFACE_WINEXINPUT,0x6c53d5fd,0x6480,0x440f,0xb6,0x18,0x47,0x67,0x50,0xc5,0xe1,0xa6 ); diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c deleted file mode 100644 index decd69b1e7e..00000000000 --- a/dlls/dinput/joystick_linux.c +++ /dev/null @@ -1,831 +0,0 @@ -/* DirectInput Joystick device - * - * Copyright 1998 Marcus Meissner - * Copyright 1998,1999 Lionel Ulmer - * Copyright 2000-2001 TransGaming Technologies Inc. - * - * 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 - */ - -/* - * To Do: - * dead zone - * force feedback - */ - -#include "config.h" -#include "wine/port.h" - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#include <fcntl.h> -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif -#include <errno.h> -#ifdef HAVE_LINUX_IOCTL_H -# include <linux/ioctl.h> -#endif -#ifdef HAVE_LINUX_JOYSTICK_H -# include <linux/joystick.h> -# undef SW_MAX -#endif -#ifdef HAVE_SYS_POLL_H -# include <sys/poll.h> -#endif - -#include "wine/debug.h" -#include "wine/unicode.h" -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "devguid.h" -#include "dinput.h" - -#include "dinput_private.h" -#include "device_private.h" -#include "joystick_private.h" - -#ifdef HAVE_LINUX_22_JOYSTICK_API - -WINE_DEFAULT_DEBUG_CHANNEL(dinput); - -#define JOYDEV_NEW "/dev/input/js" -#define JOYDEV_OLD "/dev/js" -#define JOYDEVDRIVER " (js)" - -struct JoyDev -{ - char device[MAX_PATH]; - char name[MAX_PATH]; - GUID guid_product; - - BYTE axis_count; - BYTE button_count; - int *dev_axes_map; - - WORD vendor_id, product_id, bus_type; - - BOOL is_joystick; -}; - -typedef struct JoystickImpl JoystickImpl; -static const IDirectInputDevice8WVtbl JoystickWvt; -struct JoystickImpl -{ - struct JoystickGenericImpl generic; - - struct JoyDev *joydev; - - /* joystick private */ - int joyfd; - POINTL povs[4]; -}; - -static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) -{ - return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), - JoystickGenericImpl, base), JoystickImpl, generic); -} - -static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */ - 0x9e573ed9, - 0x7734, - 0x11d2, - {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} -}; - -#define MAX_JOYSTICKS 64 -static INT joystick_devices_count = -1; -static struct JoyDev *joystick_devices; - -static void joy_polldev( IDirectInputDevice8W *iface ); - -#define SYS_PATH_FORMAT "/sys/class/input/js%d/device/id/%s" -static BOOL read_sys_id_variable(int index, const char *property, WORD *value) -{ - char sys_path[sizeof(SYS_PATH_FORMAT) + 16], id_str[5]; - int sys_fd; - BOOL ret = FALSE; - - sprintf(sys_path, SYS_PATH_FORMAT, index, property); - if ((sys_fd = open(sys_path, O_RDONLY)) != -1) - { - if (read(sys_fd, id_str, 4) == 4) - { - id_str[4] = '\0'; - *value = strtol(id_str, NULL, 16); - ret = TRUE; - } - - close(sys_fd); - } - return ret; -} -#undef SYS_PATH_FORMAT - -static INT find_joystick_devices(void) -{ - INT i; - - if (joystick_devices_count != -1) return joystick_devices_count; - - joystick_devices_count = 0; - for (i = 0; i < MAX_JOYSTICKS; i++) - { - int fd; - struct JoyDev joydev, *new_joydevs; - BYTE axes_map[ABS_MAX + 1]; - SHORT btn_map[KEY_MAX - BTN_MISC + 1]; - BOOL non_js = FALSE; - - snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i); - if ((fd = open(joydev.device, O_RDONLY)) == -1) - { - snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_OLD, i); - if ((fd = open(joydev.device, O_RDONLY)) == -1) continue; - } - - strcpy(joydev.name, "Wine Joystick"); -#if defined(JSIOCGNAME) - if (ioctl(fd, JSIOCGNAME(sizeof(joydev.name) - sizeof(JOYDEVDRIVER)), joydev.name) < 0) - WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", joydev.device, strerror(errno)); -#endif - - /* Append driver name */ - strcat(joydev.name, JOYDEVDRIVER); - - if (device_disabled_registry(joydev.name)) { - close(fd); - continue; - } - -#ifdef JSIOCGAXES - if (ioctl(fd, JSIOCGAXES, &joydev.axis_count) < 0) - { - WARN("ioctl(%s,JSIOCGAXES) failed: %s, defaulting to 2\n", joydev.device, strerror(errno)); - joydev.axis_count = 2; - } -#else - WARN("reading number of joystick axes unsupported in this platform, defaulting to 2\n"); - joydev.axis_count = 2; -#endif -#ifdef JSIOCGBUTTONS - if (ioctl(fd, JSIOCGBUTTONS, &joydev.button_count) < 0) - { - WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defaulting to 2\n", joydev.device, strerror(errno)); - joydev.button_count = 2; - } -#else - WARN("reading number of joystick buttons unsupported in this platform, defaulting to 2\n"); - joydev.button_count = 2; -#endif - - joydev.is_joystick = FALSE; - if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0) - { - WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno)); - } - else - { - INT j; - /* in lieu of properly reporting HID usage, detect presence of - * "joystick buttons" and report those devices as joysticks instead of - * gamepads */ - for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++) - { - switch (btn_map[j]) - { - case BTN_TRIGGER: - case BTN_THUMB: - case BTN_THUMB2: - case BTN_TOP: - case BTN_TOP2: - case BTN_PINKIE: - case BTN_BASE: - case BTN_BASE2: - case BTN_BASE3: - case BTN_BASE4: - case BTN_BASE5: - case BTN_BASE6: - case BTN_DEAD: - joydev.is_joystick = TRUE; - break; - case BTN_MOUSE: - case BTN_STYLUS: - non_js = TRUE; - break; - default: - break; - } - } - } - - if(non_js) - { - TRACE("Non-joystick detected. Skipping\n"); - close(fd); - continue; - } - - if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0) - { - WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno)); - joydev.dev_axes_map = NULL; - } - else - if ((joydev.dev_axes_map = HeapAlloc(GetProcessHeap(), 0, joydev.axis_count * sizeof(int)))) - { - INT j, found_axes = 0; - - /* Remap to DI numbers */ - for (j = 0; j < joydev.axis_count; j++) - { - if (axes_map[j] < 8) - { - /* Axis match 1-to-1 */ - joydev.dev_axes_map[j] = j; - found_axes++; - } - else if (axes_map[j] <= 10) - { - /* Axes 8 through 10 are Wheel, Gas and Brake, - * remap to 0, 1 and 2 - */ - joydev.dev_axes_map[j] = axes_map[j] - 8; - found_axes++; - } - else if (axes_map[j] == 16 || - axes_map[j] == 17) - { - /* POV axis */ - joydev.dev_axes_map[j] = 8; - found_axes++; - } - else - joydev.dev_axes_map[j] = -1; - } - - /* If no axes were configured but there are axes assume a 1-to-1 (wii controller) */ - if (joydev.axis_count && !found_axes) - { - int axes_limit = min(joydev.axis_count, 8); /* generic driver limit */ - - ERR("Incoherent joystick data, advertised %d axes, detected 0. Assuming 1-to-1.\n", - joydev.axis_count); - for (j = 0; j < axes_limit; j++) - joydev.dev_axes_map[j] = j; - - joydev.axis_count = axes_limit; - } - } - - /* Find vendor_id and product_id in sysfs */ - joydev.vendor_id = 0; - joydev.product_id = 0; - - read_sys_id_variable(i, "vendor", &joydev.vendor_id); - read_sys_id_variable(i, "product", &joydev.product_id); - read_sys_id_variable(i, "bustype", &joydev.bus_type); - - if (joydev.vendor_id == 0 || joydev.product_id == 0) - { - joydev.guid_product = DInput_Wine_Joystick_GUID; - } - else - { - /* Concatenate product_id with vendor_id to mimic Windows behaviour */ - joydev.guid_product = dinput_pidvid_guid; - joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id); - } - - close(fd); - - if (!joystick_devices_count) - new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev)); - else - new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joystick_devices, - (joystick_devices_count + 1) * sizeof(struct JoyDev)); - if (!new_joydevs) continue; - - TRACE("Found a joystick on %s: %s\n with %d axes and %d buttons\n", joydev.device, - joydev.name, joydev.axis_count, joydev.button_count); - - joystick_devices = new_joydevs; - joystick_devices[joystick_devices_count++] = joydev; - } - - return joystick_devices_count; -} - -static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - DWORD dwSize = lpddi->dwSize; - - TRACE("%d %p\n", dwSize, lpddi); - memset(lpddi, 0, dwSize); - - /* Return joystick */ - lpddi->dwSize = dwSize; - lpddi->guidInstance = DInput_Wine_Joystick_GUID; - lpddi->guidInstance.Data3 = id; - lpddi->guidProduct = joystick_devices[id].guid_product; - lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick); - - /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ - if (joystick_devices[id].bus_type == BUS_USB && - joystick_devices[id].vendor_id && joystick_devices[id].product_id) - { - lpddi->dwDevType |= DIDEVTYPE_HID; - lpddi->wUsagePage = 0x01; /* Desktop */ - if (joystick_devices[id].is_joystick) - lpddi->wUsage = 0x04; /* Joystick */ - else - lpddi->wUsage = 0x05; /* Game Pad */ - } - - MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH); - MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszProductName, MAX_PATH); - lpddi->guidFFDriver = GUID_NULL; -} - -static HRESULT joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - int fd = -1; - - if (id >= find_joystick_devices()) return E_FAIL; - - if (dwFlags & DIEDFL_FORCEFEEDBACK) { - WARN("force feedback not supported\n"); - return S_FALSE; - } - - if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || - (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { - /* check whether we have a joystick */ - if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1) - { - WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno)); - return S_FALSE; - } - fill_joystick_dideviceinstanceW( lpddi, version, id ); - close(fd); - TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name); - return S_OK; - } - - return S_FALSE; -} - -static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, JoystickImpl **out, unsigned short index ) -{ - DWORD i; - JoystickImpl* newDevice; - HRESULT hr; - LPDIDATAFORMAT df = NULL; - int idx = 0; - DIDEVICEINSTANCEW ddi; - - TRACE( "%s %p %p %hu\n", debugstr_guid( rguid ), dinput, out, index ); - - if (FAILED(hr = direct_input_device_alloc( sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice ))) - return hr; - df = newDevice->generic.base.data_format.wine_df; - newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit"); - - newDevice->joydev = &joystick_devices[index]; - newDevice->joyfd = -1; - newDevice->generic.guidInstance = DInput_Wine_Joystick_GUID; - newDevice->generic.guidInstance.Data3 = index; - newDevice->generic.guidProduct = DInput_Wine_Joystick_GUID; - newDevice->generic.joy_polldev = joy_polldev; - newDevice->generic.name = newDevice->joydev->name; - newDevice->generic.device_axis_count = newDevice->joydev->axis_count; - newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count; - - if (newDevice->generic.devcaps.dwButtons > 128) - { - WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons); - newDevice->generic.devcaps.dwButtons = 128; - } - - /* setup_dinput_options may change these */ - newDevice->generic.deadzone = 0; - - /* do any user specified configuration */ - hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map); - if (hr != DI_OK) - goto FAILED1; - - /* Create copy of default data format */ - memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize); - - df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons; - if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED; - - for (i = 0; i < newDevice->generic.device_axis_count; i++) - { - int wine_obj = newDevice->generic.axis_map[i]; - - if (wine_obj < 0) continue; - - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize); - if (wine_obj < 8) - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS; - else - { - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV; - i++; /* POV takes 2 axes */ - } - } - for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++) - { - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize); - df->rgodf[idx ].pguid = &GUID_Button; - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON; - } - - /* initialize default properties */ - for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) { - newDevice->generic.props[i].lDevMin = -32767; - newDevice->generic.props[i].lDevMax = +32767; - newDevice->generic.props[i].lMin = 0; - newDevice->generic.props[i].lMax = 0xffff; - newDevice->generic.props[i].lDeadZone = newDevice->generic.deadzone; /* % * 1000 */ - newDevice->generic.props[i].lSaturation = 0; - } - - newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps); - newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED; - - ddi.dwSize = sizeof(ddi); - fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index); - newDevice->generic.devcaps.dwDevType = ddi.dwDevType; - - newDevice->generic.devcaps.dwFFSamplePeriod = 0; - newDevice->generic.devcaps.dwFFMinTimeResolution = 0; - newDevice->generic.devcaps.dwFirmwareRevision = 0; - newDevice->generic.devcaps.dwHardwareRevision = 0; - newDevice->generic.devcaps.dwFFDriverVersion = 0; - - if (TRACE_ON(dinput)) { - _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df); - for (i = 0; i < (newDevice->generic.device_axis_count); i++) - TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]); - _dump_DIDEVCAPS(&newDevice->generic.devcaps); - } - - *out = newDevice; - return DI_OK; - -FAILED: - hr = DIERR_OUTOFMEMORY; -FAILED1: - if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); - HeapFree(GetProcessHeap(), 0, df); - release_DataFormat(&newDevice->generic.base.data_format); - HeapFree(GetProcessHeap(),0,newDevice->generic.axis_map); - HeapFree(GetProcessHeap(),0,newDevice); - return hr; -} - -/****************************************************************************** - * get_joystick_index : Get the joystick index from a given GUID - */ -static unsigned short get_joystick_index(REFGUID guid) -{ - GUID wine_joystick = DInput_Wine_Joystick_GUID; - GUID dev_guid = *guid; - INT i; - - wine_joystick.Data3 = 0; - dev_guid.Data3 = 0; - - /* for the standard joystick GUID use index 0 */ - if(IsEqualGUID(&GUID_Joystick,guid)) return 0; - - /* for the wine joystick GUIDs use the index stored in Data3 */ - if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3; - - for(i = 0; i < joystick_devices_count; i++) - if(IsEqualGUID(&joystick_devices[i].guid_product, guid)) return i; - - return MAX_JOYSTICKS; -} - -static HRESULT joydev_create_device( IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDevice8W **out ) -{ - unsigned short index; - - TRACE( "%p %s %p\n", dinput, debugstr_guid( rguid ), out ); - find_joystick_devices(); - *out = NULL; - - if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS && - joystick_devices_count && index < joystick_devices_count) - { - JoystickImpl *This; - HRESULT hr; - - if (FAILED(hr = alloc_device( rguid, dinput, &This, index ))) return hr; - - TRACE( "Created a Joystick device (%p)\n", This ); - - *out = &This->generic.base.IDirectInputDevice8W_iface; - return hr; - } - - return DIERR_DEVICENOTREG; -} - -#undef MAX_JOYSTICKS - -const struct dinput_device joystick_linux_device = { - "Wine Linux joystick driver", - joydev_enum_device, - joydev_create_device -}; - -/****************************************************************************** - * Acquire : gets exclusive control of the joystick - */ -static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT res; - - TRACE("(%p)\n",This); - - res = IDirectInputDevice2WImpl_Acquire(iface); - if (res != DI_OK) - return res; - - /* open the joystick device */ - if (This->joyfd==-1) { - TRACE("opening joystick device %s\n", This->joydev->device); - - This->joyfd = open(This->joydev->device, O_RDONLY); - if (This->joyfd==-1) { - ERR("open(%s) failed: %s\n", This->joydev->device, strerror(errno)); - IDirectInputDevice2WImpl_Unacquire(iface); - return DIERR_NOTFOUND; - } - } - - return DI_OK; -} - -/****************************************************************************** - * GetProperty : get input device properties - */ -static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); - _dump_DIPROPHEADER(pdiph); - - if (!IS_DIPROP(rguid)) return DI_OK; - - switch (LOWORD(rguid)) { - - case (DWORD_PTR) DIPROP_VIDPID: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - if (!This->joydev->product_id || !This->joydev->vendor_id) - return DIERR_UNSUPPORTED; - pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id); - TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData); - break; - } - case (DWORD_PTR) DIPROP_JOYSTICKID: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - pd->dwData = get_joystick_index(&This->generic.base.guid); - TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData); - break; - } - - case (DWORD_PTR) DIPROP_GUIDANDPATH: - { - static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', - 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0}; - static const WCHAR miW[] = {'m','i',0}; - static const WCHAR igW[] = {'i','g',0}; - - BOOL is_gamepad; - LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; - WORD vid = This->joydev->vendor_id; - WORD pid = This->joydev->product_id; - - if (!pid || !vid) - return DIERR_UNSUPPORTED; - - is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); - pd->guidClass = GUID_DEVCLASS_HIDCLASS; - sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid)); - - TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); - break; - } - - default: - return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); - } - - return DI_OK; -} - -/****************************************************************************** - * GetDeviceInfo : get information about a device's identity - */ -static HRESULT WINAPI JoystickLinuxWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW ddi) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p) %p\n", This, ddi); - - if (ddi == NULL) return E_POINTER; - if ((ddi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) && - (ddi->dwSize != sizeof(DIDEVICEINSTANCEW))) - return DIERR_INVALIDPARAM; - - fill_joystick_dideviceinstanceW( ddi, This->generic.base.dinput->dwVersion, - get_joystick_index(&This->generic.base.guid) ); - - ddi->guidInstance = This->generic.base.guid; - - return DI_OK; -} - -/****************************************************************************** - * Unacquire : frees the joystick - */ -static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT res; - - TRACE("(%p)\n",This); - - res = IDirectInputDevice2WImpl_Unacquire(iface); - - if (res != DI_OK) - return res; - - if (This->joyfd!=-1) { - TRACE("closing joystick device\n"); - close(This->joyfd); - This->joyfd = -1; - return DI_OK; - } - - return DI_NOEFFECT; -} - -static void joy_polldev( IDirectInputDevice8W *iface ) -{ - struct pollfd plfd; - struct js_event jse; - JoystickImpl *This = impl_from_IDirectInputDevice8W( iface ); - - TRACE("(%p)\n", This); - - if (This->joyfd==-1) { - WARN("no device\n"); - return; - } - while (1) - { - LONG value; - int inst_id = -1; - - plfd.fd = This->joyfd; - plfd.events = POLLIN; - if (poll(&plfd,1,0) != 1) - return; - /* we have one event, so we can read */ - if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) { - return; - } - TRACE("js_event: type 0x%x, number %d, value %d\n", - jse.type,jse.number,jse.value); - if (jse.type & JS_EVENT_BUTTON) - { - if (jse.number >= This->generic.devcaps.dwButtons) return; - - inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON; - This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00; - } - else if (jse.type & JS_EVENT_AXIS) - { - int number = This->generic.axis_map[jse.number]; /* wine format object index */ - - if (number < 0) return; - inst_id = number < 8 ? DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS : - DIDFT_MAKEINSTANCE(number - 8) | DIDFT_POV; - value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], jse.value); - - TRACE("changing axis %d => %d\n", jse.number, number); - switch (number) - { - case 0: This->generic.js.lX = value; break; - case 1: This->generic.js.lY = value; break; - case 2: This->generic.js.lZ = value; break; - case 3: This->generic.js.lRx = value; break; - case 4: This->generic.js.lRy = value; break; - case 5: This->generic.js.lRz = value; break; - case 6: This->generic.js.rglSlider[0] = value; break; - case 7: This->generic.js.rglSlider[1] = value; break; - case 8: case 9: case 10: case 11: - { - int idx = number - 8; - - if (jse.number % 2) - This->povs[idx].y = jse.value; - else - This->povs[idx].x = jse.value; - - This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]); - break; - } - default: - WARN("axis %d not supported\n", number); - } - } - if (inst_id >= 0) - { - queue_event(iface, inst_id, value, GetCurrentTime(), This->generic.base.dinput->evsequence++); - if (This->generic.base.hEvent) SetEvent( This->generic.base.hEvent ); - } - } -} - -static const IDirectInputDevice8WVtbl JoystickWvt = -{ - IDirectInputDevice2WImpl_QueryInterface, - IDirectInputDevice2WImpl_AddRef, - JoystickWGenericImpl_Release, - JoystickWGenericImpl_GetCapabilities, - IDirectInputDevice2WImpl_EnumObjects, - JoystickLinuxWImpl_GetProperty, - JoystickWGenericImpl_SetProperty, - JoystickLinuxWImpl_Acquire, - JoystickLinuxWImpl_Unacquire, - JoystickWGenericImpl_GetDeviceState, - IDirectInputDevice2WImpl_GetDeviceData, - IDirectInputDevice2WImpl_SetDataFormat, - IDirectInputDevice2WImpl_SetEventNotification, - IDirectInputDevice2WImpl_SetCooperativeLevel, - JoystickWGenericImpl_GetObjectInfo, - JoystickLinuxWImpl_GetDeviceInfo, - IDirectInputDevice2WImpl_RunControlPanel, - IDirectInputDevice2WImpl_Initialize, - IDirectInputDevice2WImpl_CreateEffect, - IDirectInputDevice2WImpl_EnumEffects, - IDirectInputDevice2WImpl_GetEffectInfo, - IDirectInputDevice2WImpl_GetForceFeedbackState, - IDirectInputDevice2WImpl_SendForceFeedbackCommand, - IDirectInputDevice2WImpl_EnumCreatedEffectObjects, - IDirectInputDevice2WImpl_Escape, - JoystickWGenericImpl_Poll, - IDirectInputDevice2WImpl_SendDeviceData, - IDirectInputDevice7WImpl_EnumEffectsInFile, - IDirectInputDevice7WImpl_WriteEffectToFile, - JoystickWGenericImpl_BuildActionMap, - JoystickWGenericImpl_SetActionMap, - IDirectInputDevice8WImpl_GetImageInfo -}; - -#else /* HAVE_LINUX_22_JOYSTICK_API */ - -const struct dinput_device joystick_linux_device = { - "Wine Linux joystick driver", - NULL, - NULL, -}; - -#endif /* HAVE_LINUX_22_JOYSTICK_API */ diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c deleted file mode 100644 index c7f4cc486fd..00000000000 --- a/dlls/dinput/joystick_linuxinput.c +++ /dev/null @@ -1,1276 +0,0 @@ -/* DirectInput Joystick device - * - * Copyright 1998,2000 Marcus Meissner - * Copyright 1998,1999 Lionel Ulmer - * Copyright 2000-2001 TransGaming Technologies Inc. - * Copyright 2005 Daniel Remenak - * - * 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 "config.h" -#include "wine/port.h" - -#include <assert.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#include <fcntl.h> -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif -#include <errno.h> -#ifdef HAVE_LINUX_INPUT_H -# include <linux/input.h> -# undef SW_MAX -# if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE) -# define HAS_PROPER_HEADER -# endif -#endif -#ifdef HAVE_SYS_POLL_H -# include <sys/poll.h> -#endif - -#include "wine/debug.h" -#include "wine/unicode.h" -#include "wine/list.h" -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "devguid.h" -#include "dinput.h" - -#include "dinput_private.h" -#include "device_private.h" -#include "joystick_private.h" - -#ifdef HAS_PROPER_HEADER - -WINE_DEFAULT_DEBUG_CHANNEL(dinput); - -#define EVDEVPREFIX "/dev/input/event" -#define EVDEVDRIVER " (event)" - -/* Wine joystick driver object instances */ -#define WINE_JOYSTICK_MAX_AXES 8 -#define WINE_JOYSTICK_MAX_POVS 4 -#define WINE_JOYSTICK_MAX_BUTTONS 128 - -struct wine_input_absinfo { - LONG value; - LONG minimum; - LONG maximum; - LONG fuzz; - LONG flat; -}; - -/* implemented in effect_linuxinput.c */ -HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff); -HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info); -HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info); - -static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags); - -typedef struct JoystickImpl JoystickImpl; -static const IDirectInputDevice8WVtbl JoystickWvt; - -struct JoyDev { - char *device; - char *name; - GUID guid; - GUID guid_product; - - BOOL has_ff, is_joystick; - int num_effects; - - /* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */ - BYTE evbits[(EV_MAX+7)/8]; - BYTE absbits[(ABS_MAX+7)/8]; - BYTE keybits[(KEY_MAX+7)/8]; - BYTE ffbits[(FF_MAX+7)/8]; - - /* data returned by the EVIOCGABS() ioctl */ - struct wine_input_absinfo axes[ABS_MAX]; - - WORD vendor_id, product_id, bus_type; -}; - -struct JoystickImpl -{ - struct JoystickGenericImpl generic; - struct JoyDev *joydev; - - /* joystick private */ - int joyfd; - - int dev_axes_to_di[ABS_MAX]; - POINTL povs[4]; - - /* LUT for KEY_ to offset in rgbButtons */ - BYTE buttons[KEY_MAX]; - - /* Force feedback variables */ - struct list ff_effects; - int ff_state; - int ff_autocenter; - int ff_gain; -}; - -static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) -{ - return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), - JoystickGenericImpl, base), JoystickImpl, generic); -} - -static void fake_current_js_state(JoystickImpl *ji); -static void find_joydevs(void); -static void joy_polldev( IDirectInputDevice8W *iface ); - -/* This GUID is slightly different from the linux joystick one. Take note. */ -static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */ - 0x9e573eda, - 0x7734, - 0x11d2, - {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} -}; - -#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7))) - -#define MAX_JOYDEV 64 - -static int have_joydevs = -1; -static struct JoyDev *joydevs = NULL; - -static void find_joydevs(void) -{ - int i; - - if (InterlockedCompareExchange(&have_joydevs, 0, -1) != -1) - /* Someone beat us to it */ - return; - - for (i = 0; i < MAX_JOYDEV; i++) - { - char buf[MAX_PATH]; - struct JoyDev joydev = {0}; - int fd; - BOOL no_ff_check = FALSE; - int j; - struct JoyDev *new_joydevs; - struct input_id device_id = {0}; - - snprintf(buf, sizeof(buf), EVDEVPREFIX"%d", i); - - if ((fd = open(buf, O_RDWR)) == -1) - { - fd = open(buf, O_RDONLY); - no_ff_check = TRUE; - } - - if (fd == -1) - continue; - - if (ioctl(fd, EVIOCGBIT(0, sizeof(joydev.evbits)), joydev.evbits) == -1) - { - WARN("ioctl(EVIOCGBIT, 0) failed: %d %s\n", errno, strerror(errno)); - close(fd); - continue; - } - if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(joydev.absbits)), joydev.absbits) == -1) - { - WARN("ioctl(EVIOCGBIT, EV_ABS) failed: %d %s\n", errno, strerror(errno)); - close(fd); - continue; - } - if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(joydev.keybits)), joydev.keybits) == -1) - { - WARN("ioctl(EVIOCGBIT, EV_KEY) failed: %d %s\n", errno, strerror(errno)); - close(fd); - continue; - } - - /* A true joystick has at least axis X and Y, and at least 1 - * button. copied from linux/drivers/input/joydev.c */ - if (((!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y)) && - !test_bit(joydev.absbits, ABS_WHEEL) && - !test_bit(joydev.absbits, ABS_GAS) && - !test_bit(joydev.absbits, ABS_BRAKE)) || - !(test_bit(joydev.keybits, BTN_TRIGGER) || - test_bit(joydev.keybits, BTN_A) || - test_bit(joydev.keybits, BTN_1) || - test_bit(joydev.keybits, BTN_BASE) || - test_bit(joydev.keybits, BTN_GEAR_UP) || - test_bit(joydev.keybits, BTN_GEAR_DOWN))) - { - close(fd); - continue; - } - - /* in lieu of properly reporting HID usage, detect presence of - * "joystick buttons" and report those devices as joysticks instead of - * gamepads */ - joydev.is_joystick = - test_bit(joydev.keybits, BTN_TRIGGER) || - test_bit(joydev.keybits, BTN_THUMB) || - test_bit(joydev.keybits, BTN_THUMB2) || - test_bit(joydev.keybits, BTN_TOP) || - test_bit(joydev.keybits, BTN_TOP2) || - test_bit(joydev.keybits, BTN_PINKIE) || - test_bit(joydev.keybits, BTN_BASE) || - test_bit(joydev.keybits, BTN_BASE2) || - test_bit(joydev.keybits, BTN_BASE3) || - test_bit(joydev.keybits, BTN_BASE4) || - test_bit(joydev.keybits, BTN_BASE5) || - test_bit(joydev.keybits, BTN_BASE6) || - test_bit(joydev.keybits, BTN_GEAR_UP) || - test_bit(joydev.keybits, BTN_GEAR_DOWN) || - test_bit(joydev.keybits, BTN_DEAD); - - if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1))) - { - close(fd); - continue; - } - strcpy(joydev.device, buf); - - buf[MAX_PATH - 1] = 0; - if (ioctl(fd, EVIOCGNAME(MAX_PATH - 1), buf) != -1 && - (joydev.name = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + strlen(EVDEVDRIVER) + 1))) - { - strcpy(joydev.name, buf); - /* Append driver name */ - strcat(joydev.name, EVDEVDRIVER); - } - else - joydev.name = joydev.device; - - if (device_disabled_registry(joydev.name)) { - close(fd); - HeapFree(GetProcessHeap(), 0, joydev.name); - if (joydev.name != joydev.device) - HeapFree(GetProcessHeap(), 0, joydev.device); - continue; - } - - joydev.guid = DInput_Wine_Joystick_Base_GUID; - joydev.guid.Data3 += have_joydevs; - - TRACE("Found a joystick on %s: %s (%s)\n", - joydev.device, joydev.name, - debugstr_guid(&joydev.guid) - ); - -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - if (!no_ff_check && - test_bit(joydev.evbits, EV_FF) && - ioctl(fd, EVIOCGBIT(EV_FF, sizeof(joydev.ffbits)), joydev.ffbits) != -1 && - ioctl(fd, EVIOCGEFFECTS, &joydev.num_effects) != -1 && - joydev.num_effects > 0) - { - TRACE(" ... with force feedback\n"); - joydev.has_ff = TRUE; - } -#endif - - for (j = 0; j < ABS_MAX;j ++) - { - if (!test_bit(joydev.absbits, j)) continue; - if (ioctl(fd, EVIOCGABS(j), &(joydev.axes[j])) != -1) - { - TRACE(" ... with axis %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n", - j, - joydev.axes[j].value, - joydev.axes[j].minimum, - joydev.axes[j].maximum, - joydev.axes[j].fuzz, - joydev.axes[j].flat - ); - } - } - - if (ioctl(fd, EVIOCGID, &device_id) == -1) - { - WARN("ioctl(EVIOCGID) failed: %d %s\n", errno, strerror(errno)); - joydev.guid_product = DInput_Wine_Joystick_Base_GUID; - } - else - { - joydev.vendor_id = device_id.vendor; - joydev.product_id = device_id.product; - joydev.bus_type = device_id.bustype; - - /* Concatenate product_id with vendor_id to mimic Windows behaviour */ - joydev.guid_product = dinput_pidvid_guid; - joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id); - } - - if (!have_joydevs) - new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev)); - else - new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joydevs, (1 + have_joydevs) * sizeof(struct JoyDev)); - - if (!new_joydevs) - { - close(fd); - continue; - } - joydevs = new_joydevs; - joydevs[have_joydevs] = joydev; - have_joydevs++; - - close(fd); - } -} - -static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - DWORD dwSize = lpddi->dwSize; - - TRACE("%d %p\n", dwSize, lpddi); - memset(lpddi, 0, dwSize); - - lpddi->dwSize = dwSize; - lpddi->guidInstance = joydevs[id].guid; - lpddi->guidProduct = joydevs[id].guid_product; - lpddi->guidFFDriver = GUID_NULL; - lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick); - - /* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */ - if (joydevs[id].bus_type == BUS_USB && - joydevs[id].vendor_id && joydevs[id].product_id) - { - lpddi->dwDevType |= DIDEVTYPE_HID; - lpddi->wUsagePage = 0x01; /* Desktop */ - if (joydevs[id].is_joystick) - lpddi->wUsage = 0x04; /* Joystick */ - else - lpddi->wUsage = 0x05; /* Game Pad */ - } - - MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); - MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszProductName, MAX_PATH); -} - -static HRESULT joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - find_joydevs(); - - if (id >= have_joydevs) { - return E_FAIL; - } - - if (!((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || - (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))) - return S_FALSE; - -#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION - if (dwFlags & DIEDFL_FORCEFEEDBACK) - return S_FALSE; -#endif - - if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) { - fill_joystick_dideviceinstanceW(lpddi, version, id); - return S_OK; - } - return S_FALSE; -} - -static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, JoystickImpl **out, unsigned short index ) -{ - JoystickImpl* newDevice; - LPDIDATAFORMAT df = NULL; - int i, idx = 0; - int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2]; - DIDEVICEINSTANCEW ddi; - HRESULT hr; - - if (FAILED(hr = direct_input_device_alloc( sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice ))) - return hr; - df = newDevice->generic.base.data_format.wine_df; - newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); - - newDevice->generic.joy_polldev = joy_polldev; - newDevice->joyfd = -1; - newDevice->joydev = &joydevs[index]; - newDevice->generic.name = newDevice->joydev->name; - list_init(&newDevice->ff_effects); -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - newDevice->ff_state = FF_STATUS_STOPPED; -#endif - /* There is no way in linux to query force feedback autocenter status. - Instead, track it with ff_autocenter, and assume it's initially - enabled. */ - newDevice->ff_autocenter = 1; - newDevice->ff_gain = 0xFFFF; - - /* Count number of available axes - supported Axis & POVs */ - for (i = 0; i < ABS_MAX; i++) - { - if (idx < WINE_JOYSTICK_MAX_AXES && - i < ABS_HAT0X && - test_bit(newDevice->joydev->absbits, i)) - { - newDevice->generic.device_axis_count++; - newDevice->dev_axes_to_di[i] = idx; - newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum; - newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum; - if (i >= 8 && i <= 10) /* If it's a wheel axis... */ - default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */ - else - default_axis_map[idx] = i; - idx++; - } - else - newDevice->dev_axes_to_di[i] = -1; - } - - for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++) - { - if (test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) && - test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2)) - { - newDevice->generic.device_axis_count += 2; - newDevice->generic.props[idx ].lDevMin = newDevice->joydev->axes[ABS_HAT0X + i * 2].minimum; - newDevice->generic.props[idx ].lDevMax = newDevice->joydev->axes[ABS_HAT0X + i * 2].maximum; - newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = idx; - newDevice->generic.props[idx+1].lDevMin = newDevice->joydev->axes[ABS_HAT0Y + i * 2].minimum; - newDevice->generic.props[idx+1].lDevMax = newDevice->joydev->axes[ABS_HAT0Y + i * 2].maximum; - newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1; - - default_axis_map[idx] = default_axis_map[idx + 1] = WINE_JOYSTICK_MAX_AXES + i; - idx += 2; - } - else - newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1; - } - - /* do any user specified configuration */ - if (setup_dinput_options(&newDevice->generic, default_axis_map) != DI_OK) goto failed; - - /* Create copy of default data format */ - memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize); - if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed; - - - /* Construct internal data format */ - - /* Supported Axis & POVs */ - for (i = 0, idx = 0; i < newDevice->generic.device_axis_count; i++) - { - int wine_obj = newDevice->generic.axis_map[i]; - - if (wine_obj < 0) continue; - - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize); - if (wine_obj < 8) - df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS; - else - { - df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV; - i++; /* POV takes 2 axes */ - } - - newDevice->generic.props[idx].lMin = 0; - newDevice->generic.props[idx].lMax = 0xffff; - newDevice->generic.props[idx].lSaturation = 0; - newDevice->generic.props[idx].lDeadZone = newDevice->generic.deadzone; - - /* Linux supports force-feedback on X & Y axes only */ - if (newDevice->joydev->has_ff && (i == 0 || i == 1)) - df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR; - - idx++; - } - - /* Buttons can be anywhere, so check all */ - for (i = 0; i < KEY_MAX && newDevice->generic.devcaps.dwButtons < WINE_JOYSTICK_MAX_BUTTONS; i++) - { - if (!test_bit(newDevice->joydev->keybits, i)) continue; - - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[newDevice->generic.devcaps.dwButtons + 12], df->dwObjSize); - newDevice->buttons[i] = 0x80 | newDevice->generic.devcaps.dwButtons; - df->rgodf[idx ].pguid = &GUID_Button; - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->generic.devcaps.dwButtons++) | DIDFT_PSHBUTTON; - } - df->dwNumObjs = idx; - - fake_current_js_state(newDevice); - - /* Fill the caps */ - newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps); - newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED; - - ddi.dwSize = sizeof(ddi); - fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index); - newDevice->generic.devcaps.dwDevType = ddi.dwDevType; - - if (newDevice->joydev->has_ff) - newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK; - - *out = newDevice; - return DI_OK; - -failed: - if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); - HeapFree(GetProcessHeap(), 0, df); - HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map); - HeapFree(GetProcessHeap(), 0, newDevice); - return DIERR_OUTOFMEMORY; -} - -/****************************************************************************** - * get_joystick_index : Get the joystick index from a given GUID - */ -static unsigned short get_joystick_index(REFGUID guid) -{ - GUID wine_joystick = DInput_Wine_Joystick_Base_GUID; - GUID dev_guid = *guid; - INT i; - - wine_joystick.Data3 = 0; - dev_guid.Data3 = 0; - - /* for the standard joystick GUID use index 0 */ - if(IsEqualGUID(&GUID_Joystick,guid)) return 0; - - /* for the wine joystick GUIDs use the index stored in Data3 */ - if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3 - DInput_Wine_Joystick_Base_GUID.Data3; - - for(i = 0; i < have_joydevs; i++) - if(IsEqualGUID(&joydevs[i].guid_product, guid)) return i; - - return MAX_JOYDEV; -} - -static HRESULT joydev_create_device( IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDevice8W **out ) -{ - unsigned short index; - - TRACE( "%p %s %p\n", dinput, debugstr_guid( rguid ), out ); - find_joydevs(); - *out = NULL; - - if ((index = get_joystick_index(rguid)) < MAX_JOYDEV && - have_joydevs && index < have_joydevs) - { - JoystickImpl *This; - HRESULT hr; - - if (FAILED(hr = alloc_device( rguid, dinput, &This, index ))) return hr; - - TRACE( "Created a Joystick device (%p)\n", This ); - - *out = &This->generic.base.IDirectInputDevice8W_iface; - return DI_OK; - } - - return DIERR_DEVICENOTREG; -} - - -const struct dinput_device joystick_linuxinput_device = { - "Wine Linux-input joystick driver", - joydev_enum_device, - joydev_create_device -}; - -/****************************************************************************** - * Acquire : gets exclusive control of the joystick - */ -static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT res; - - TRACE("(this=%p)\n",This); - - if ((res = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK) - { - WARN("Failed to acquire: %x\n", res); - return res; - } - - if ((This->joyfd = open(This->joydev->device, O_RDWR)) == -1) - { - if ((This->joyfd = open(This->joydev->device, O_RDONLY)) == -1) - { - /* Couldn't open the device at all */ - ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno)); - IDirectInputDevice2WImpl_Unacquire(iface); - return DIERR_NOTFOUND; - } - else - { - /* Couldn't open in r/w but opened in read-only. */ - WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device); - } - } - else - { - struct input_event event; - - event.type = EV_FF; - event.code = FF_GAIN; - event.value = This->ff_gain; - if (write(This->joyfd, &event, sizeof(event)) == -1) - ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno)); - if (!This->ff_autocenter) - { - /* Disable autocenter. */ - event.code = FF_AUTOCENTER; - event.value = 0; - if (write(This->joyfd, &event, sizeof(event)) == -1) - ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno)); - } - } - - return DI_OK; -} - -/****************************************************************************** - * Unacquire : frees the joystick - */ -static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT res; - - TRACE("(this=%p)\n",This); - res = IDirectInputDevice2WImpl_Unacquire(iface); - if (res==DI_OK && This->joyfd!=-1) { - struct input_event event; - - /* Stop and unload all effects */ - JoystickWImpl_SendForceFeedbackCommand(iface, DISFFC_RESET); - - /* Enable autocenter. */ - event.type = EV_FF; - event.code = FF_AUTOCENTER; - /* TODO: Read autocenter strength before disabling it, and use it here - * instead of 0xFFFF (maximum strength). - */ - event.value = 0xFFFF; - if (write(This->joyfd, &event, sizeof(event)) == -1) - ERR("Failed to set autocenter to %04x: %d %s\n", event.value, errno, strerror(errno)); - - close(This->joyfd); - This->joyfd = -1; - } - return res; -} - -/* - * set the current state of the js device as it would be with the middle - * values on the axes - */ -#define CENTER_AXIS(a) \ - (ji->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis( &ji->generic.props[ji->dev_axes_to_di[a]], \ - ji->joydev->axes[a].value )) -static void fake_current_js_state(JoystickImpl *ji) -{ - int i; - - /* center the axes */ - ji->generic.js.lX = CENTER_AXIS(ABS_X); - ji->generic.js.lY = CENTER_AXIS(ABS_Y); - ji->generic.js.lZ = CENTER_AXIS(ABS_Z); - ji->generic.js.lRx = CENTER_AXIS(ABS_RX); - ji->generic.js.lRy = CENTER_AXIS(ABS_RY); - ji->generic.js.lRz = CENTER_AXIS(ABS_RZ); - ji->generic.js.rglSlider[0] = CENTER_AXIS(ABS_THROTTLE); - ji->generic.js.rglSlider[1] = CENTER_AXIS(ABS_RUDDER); - - /* POV center is -1 */ - for (i = 0; i < 4; i++) - ji->generic.js.rgdwPOV[i] = -1; -} -#undef CENTER_AXIS - -/* convert wine format offset to user format object index */ -static void joy_polldev( IDirectInputDevice8W *iface ) -{ - struct pollfd plfd; - struct input_event ie; - JoystickImpl *This = impl_from_IDirectInputDevice8W( iface ); - - if (This->joyfd==-1) - return; - - while (1) - { - LONG value = 0; - int inst_id = -1; - - plfd.fd = This->joyfd; - plfd.events = POLLIN; - - if (poll(&plfd,1,0) != 1) - return; - - /* we have one event, so we can read */ - if (sizeof(ie)!=read(This->joyfd,&ie,sizeof(ie))) - return; - - TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value); - switch (ie.type) { - case EV_KEY: /* button */ - { - int btn = This->buttons[ie.code]; - - TRACE("(%p) %d -> %d\n", This, ie.code, btn); - if (btn & 0x80) - { - btn &= 0x7F; - inst_id = DIDFT_MAKEINSTANCE(btn) | DIDFT_PSHBUTTON; - This->generic.js.rgbButtons[btn] = value = ie.value ? 0x80 : 0x00; - } - break; - } - case EV_ABS: - { - int axis = This->dev_axes_to_di[ie.code]; - - /* User axis remapping */ - if (axis < 0) break; - axis = This->generic.axis_map[axis]; - if (axis < 0) break; - - inst_id = axis < 8 ? DIDFT_MAKEINSTANCE(axis) | DIDFT_ABSAXIS : - DIDFT_MAKEINSTANCE(axis - 8) | DIDFT_POV; - value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], ie.value); - - switch (axis) { - case 0: This->generic.js.lX = value; break; - case 1: This->generic.js.lY = value; break; - case 2: This->generic.js.lZ = value; break; - case 3: This->generic.js.lRx = value; break; - case 4: This->generic.js.lRy = value; break; - case 5: This->generic.js.lRz = value; break; - case 6: This->generic.js.rglSlider[0] = value; break; - case 7: This->generic.js.rglSlider[1] = value; break; - case 8: case 9: case 10: case 11: - { - int idx = axis - 8; - - if (ie.code % 2) - This->povs[idx].y = ie.value; - else - This->povs[idx].x = ie.value; - - This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]); - break; - } - default: - FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value); - } - break; - } -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - case EV_FF_STATUS: - This->ff_state = ie.value; - break; -#endif -#ifdef EV_SYN - case EV_SYN: - /* there is nothing to do */ - break; -#endif -#ifdef EV_MSC - case EV_MSC: - /* Ignore */ - break; -#endif - default: - TRACE("skipping event\n"); - break; - } - if (inst_id >= 0) - { - queue_event(iface, inst_id, - value, GetCurrentTime(), This->generic.base.dinput->evsequence++); - if (This->generic.base.hEvent) SetEvent( This->generic.base.hEvent ); - } - } -} - -/****************************************************************************** - * SetProperty : change input device properties - */ -static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - if (!ph) { - WARN("invalid argument\n"); - return DIERR_INVALIDPARAM; - } - - TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); - TRACE("ph.dwSize = %d, ph.dwHeaderSize =%d, ph.dwObj = %d, ph.dwHow= %d\n", - ph->dwSize, ph->dwHeaderSize, ph->dwObj, ph->dwHow); - - if (IS_DIPROP(rguid)) { - switch (LOWORD(rguid)) { - case (DWORD_PTR)DIPROP_AUTOCENTER: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - - TRACE("autocenter(%d)\n", pd->dwData); - This->ff_autocenter = pd->dwData == DIPROPAUTOCENTER_ON; - - break; - } - case (DWORD_PTR)DIPROP_FFGAIN: { - LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; - - TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData); - This->ff_gain = MulDiv(pd->dwData, 0xFFFF, 10000); - if (This->generic.base.acquired) { - /* Update immediately. */ - struct input_event event; - - event.type = EV_FF; - event.code = FF_GAIN; - event.value = This->ff_gain; - if (write(This->joyfd, &event, sizeof(event)) == -1) - ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno)); - } - break; - } - default: - return JoystickWGenericImpl_SetProperty(iface, rguid, ph); - } - } - return DI_OK; -} - -/****************************************************************************** - * GetProperty : get input device properties - */ -static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); - _dump_DIPROPHEADER(pdiph); - - if (!IS_DIPROP(rguid)) return DI_OK; - - switch (LOWORD(rguid)) { - case (DWORD_PTR) DIPROP_AUTOCENTER: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - pd->dwData = This->ff_autocenter ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF; - TRACE("autocenter(%d)\n", pd->dwData); - break; - } - case (DWORD_PTR) DIPROP_FFGAIN: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - pd->dwData = MulDiv(This->ff_gain, 10000, 0xFFFF); - TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData); - break; - } - - case (DWORD_PTR) DIPROP_VIDPID: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - if (!This->joydev->product_id || !This->joydev->vendor_id) - return DIERR_UNSUPPORTED; - pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id); - TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData); - break; - } - - case (DWORD_PTR) DIPROP_JOYSTICKID: - { - LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; - - pd->dwData = get_joystick_index(&This->generic.base.guid); - TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData); - break; - } - - case (DWORD_PTR) DIPROP_GUIDANDPATH: - { - static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', - 'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0}; - static const WCHAR miW[] = {'m','i',0}; - static const WCHAR igW[] = {'i','g',0}; - - BOOL is_gamepad; - LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; - WORD vid = This->joydev->vendor_id; - WORD pid = This->joydev->product_id; - - if (!pid || !vid) - return DIERR_UNSUPPORTED; - - is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); - pd->guidClass = GUID_DEVCLASS_HIDCLASS; - sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid)); - - TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); - break; - } - - default: - return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); - } - - return DI_OK; -} - -/****************************************************************************** - * CreateEffect - Create a new FF effect with the specified params - */ -static HRESULT WINAPI JoystickWImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, - LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef, - LPUNKNOWN pUnkOuter) -{ -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - effect_list_item* new_effect = NULL; - HRESULT retval = DI_OK; -#endif - - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter); - - *ppdef = NULL; - if (!This->joydev->has_ff) - { - TRACE("No force feedback support\n"); - return DIERR_UNSUPPORTED; - } - -#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION - TRACE("not available (compiled w/o force feedback support)\n"); - return DIERR_UNSUPPORTED; -#else - - if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect)))) - return DIERR_OUTOFMEMORY; - - retval = linuxinput_create_effect(&This->joyfd, rguid, &new_effect->entry, &new_effect->ref); - if (retval != DI_OK) - { - HeapFree(GetProcessHeap(), 0, new_effect); - return retval; - } - - if (lpeff != NULL) - { - retval = IDirectInputEffect_SetParameters(new_effect->ref, lpeff, - DIEP_AXES | DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE | - DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON | - DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS); - - if (retval != DI_OK && retval != DI_DOWNLOADSKIPPED) - { - HeapFree(GetProcessHeap(), 0, new_effect); - return retval; - } - } - - list_add_tail(&This->ff_effects, &new_effect->entry); - *ppdef = new_effect->ref; - - if (pUnkOuter != NULL) - FIXME("Interface aggregation not implemented.\n"); - - return DI_OK; - -#endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */ -} - -/******************************************************************************* - * EnumEffects - Enumerate available FF effects - */ -static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, - LPDIENUMEFFECTSCALLBACKW lpCallback, - LPVOID pvRef, - DWORD dwEffType) -{ -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - /* seems silly to duplicate all this code but all the structures and functions - * are actually different (A/W) */ - DIEFFECTINFOW dei; /* feif */ - DWORD type = DIEFT_GETTYPE(dwEffType); - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - int xfd = This->joyfd; - - TRACE("(this=%p,%p,%d) type=%d fd=%d\n", This, pvRef, dwEffType, type, xfd); - - dei.dwSize = sizeof(DIEFFECTINFOW); - - if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE) - && test_bit(This->joydev->ffbits, FF_CONSTANT)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce); - (*lpCallback)(&dei, pvRef); - } - - if ((type == DIEFT_ALL || type == DIEFT_PERIODIC) - && test_bit(This->joydev->ffbits, FF_PERIODIC)) { - if (test_bit(This->joydev->ffbits, FF_SQUARE)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_SINE)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_SAW_UP)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown); - (*lpCallback)(&dei, pvRef); - } - } - - if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE) - && test_bit(This->joydev->ffbits, FF_RAMP)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce); - (*lpCallback)(&dei, pvRef); - } - - if (type == DIEFT_ALL || type == DIEFT_CONDITION) { - if (test_bit(This->joydev->ffbits, FF_SPRING)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_DAMPER)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_INERTIA)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia); - (*lpCallback)(&dei, pvRef); - } - if (test_bit(This->joydev->ffbits, FF_FRICTION)) { - IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction); - (*lpCallback)(&dei, pvRef); - } - } - - /* return to unacquired state if that's where it was */ - if (xfd == -1) - IDirectInputDevice8_Unacquire(iface); -#endif - - return DI_OK; -} - -/******************************************************************************* - * GetEffectInfo - Get information about a particular effect - */ -static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, - LPDIEFFECTINFOW pdei, - REFGUID guid) -{ - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid)); - -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - return linuxinput_get_info_W(This->joyfd, guid, pdei); -#else - return DI_OK; -#endif -} - -/******************************************************************************* - * GetForceFeedbackState - Get information about the device's FF state - */ -static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) -{ - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(this=%p,%p)\n", This, pdwOut); - - (*pdwOut) = 0; - -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - /* DIGFFS_STOPPED is the only mandatory flag to report */ - if (This->ff_state == FF_STATUS_STOPPED) - (*pdwOut) |= DIGFFS_STOPPED; -#endif - - return DI_OK; -} - -/******************************************************************************* - * SendForceFeedbackCommand - Send a command to the device's FF system - */ -static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) -{ - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - TRACE("(this=%p,%d)\n", This, dwFlags); - -#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - switch (dwFlags) - { - case DISFFC_STOPALL: - { - effect_list_item *itr; - - /* Stop all effects */ - LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry) - IDirectInputEffect_Stop(itr->ref); - break; - } - - case DISFFC_RESET: - { - effect_list_item *itr; - - /* Stop and unload all effects. It is not true that effects are released */ - LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry) - { - IDirectInputEffect_Stop(itr->ref); - IDirectInputEffect_Unload(itr->ref); - } - break; - } - case DISFFC_PAUSE: - case DISFFC_CONTINUE: - FIXME("No support for Pause or Continue in linux\n"); - break; - - case DISFFC_SETACTUATORSOFF: - case DISFFC_SETACTUATORSON: - FIXME("No direct actuator control in linux\n"); - break; - - default: - WARN("Unknown Force Feedback Command %u!\n", dwFlags); - return DIERR_INVALIDPARAM; - } - return DI_OK; -#else - return DIERR_UNSUPPORTED; -#endif -} - -/******************************************************************************* - * EnumCreatedEffectObjects - Enumerate all the effects that have been - * created for this device. - */ -static HRESULT WINAPI JoystickWImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface, - LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, - LPVOID pvRef, DWORD dwFlags) -{ - /* this function is safe to call on non-ff-enabled builds */ - JoystickImpl* This = impl_from_IDirectInputDevice8W(iface); - effect_list_item *itr, *ptr; - - TRACE("(this=%p,%p,%p,%d)\n", This, lpCallback, pvRef, dwFlags); - - if (!lpCallback) - return DIERR_INVALIDPARAM; - - if (dwFlags != 0) - FIXME("Flags specified, but no flags exist yet (DX9)!\n"); - - LIST_FOR_EACH_ENTRY_SAFE(itr, ptr, &This->ff_effects, effect_list_item, entry) - (*lpCallback)(itr->ref, pvRef); - - return DI_OK; -} - -/****************************************************************************** - * GetDeviceInfo : get information about a device's identity - */ -static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, - LPDIDEVICEINSTANCEW pdidi) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p) %p\n", This, pdidi); - - if (pdidi == NULL) return E_POINTER; - if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) && - (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) - return DIERR_INVALIDPARAM; - - fill_joystick_dideviceinstanceW(pdidi, This->generic.base.dinput->dwVersion, - get_joystick_index(&This->generic.base.guid)); - - pdidi->guidInstance = This->generic.base.guid; - - return DI_OK; -} - -static const IDirectInputDevice8WVtbl JoystickWvt = -{ - IDirectInputDevice2WImpl_QueryInterface, - IDirectInputDevice2WImpl_AddRef, - JoystickWGenericImpl_Release, - JoystickWGenericImpl_GetCapabilities, - IDirectInputDevice2WImpl_EnumObjects, - JoystickWImpl_GetProperty, - JoystickWImpl_SetProperty, - JoystickWImpl_Acquire, - JoystickWImpl_Unacquire, - JoystickWGenericImpl_GetDeviceState, - IDirectInputDevice2WImpl_GetDeviceData, - IDirectInputDevice2WImpl_SetDataFormat, - IDirectInputDevice2WImpl_SetEventNotification, - IDirectInputDevice2WImpl_SetCooperativeLevel, - JoystickWGenericImpl_GetObjectInfo, - JoystickWImpl_GetDeviceInfo, - IDirectInputDevice2WImpl_RunControlPanel, - IDirectInputDevice2WImpl_Initialize, - JoystickWImpl_CreateEffect, - JoystickWImpl_EnumEffects, - JoystickWImpl_GetEffectInfo, - JoystickWImpl_GetForceFeedbackState, - JoystickWImpl_SendForceFeedbackCommand, - JoystickWImpl_EnumCreatedEffectObjects, - IDirectInputDevice2WImpl_Escape, - JoystickWGenericImpl_Poll, - IDirectInputDevice2WImpl_SendDeviceData, - IDirectInputDevice7WImpl_EnumEffectsInFile, - IDirectInputDevice7WImpl_WriteEffectToFile, - JoystickWGenericImpl_BuildActionMap, - JoystickWGenericImpl_SetActionMap, - IDirectInputDevice8WImpl_GetImageInfo -}; - -#else /* HAS_PROPER_HEADER */ - -const struct dinput_device joystick_linuxinput_device = { - "Wine Linux-input joystick driver", - NULL, - NULL, -}; - -#endif /* HAS_PROPER_HEADER */ diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c deleted file mode 100644 index 5796daf8e11..00000000000 --- a/dlls/dinput/joystick_osx.c +++ /dev/null @@ -1,1704 +0,0 @@ -/* DirectInput Joystick device for Mac OS/X - * - * Copyright 1998 Marcus Meissner - * Copyright 1998,1999 Lionel Ulmer - * Copyright 2000-2001 TransGaming Technologies Inc. - * Copyright 2009 CodeWeavers, Aric Stewart - * - * 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 "config.h" -#include "wine/port.h" - -#if defined(HAVE_IOKIT_HID_IOHIDLIB_H) -#define DWORD UInt32 -#define LPDWORD UInt32* -#define LONG SInt32 -#define LPLONG SInt32* -#define E_PENDING __carbon_E_PENDING -#define ULONG __carbon_ULONG -#define E_INVALIDARG __carbon_E_INVALIDARG -#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY -#define E_HANDLE __carbon_E_HANDLE -#define E_ACCESSDENIED __carbon_E_ACCESSDENIED -#define E_UNEXPECTED __carbon_E_UNEXPECTED -#define E_FAIL __carbon_E_FAIL -#define E_ABORT __carbon_E_ABORT -#define E_POINTER __carbon_E_POINTER -#define E_NOINTERFACE __carbon_E_NOINTERFACE -#define E_NOTIMPL __carbon_E_NOTIMPL -#define S_FALSE __carbon_S_FALSE -#define S_OK __carbon_S_OK -#define HRESULT_FACILITY __carbon_HRESULT_FACILITY -#define IS_ERROR __carbon_IS_ERROR -#define FAILED __carbon_FAILED -#define SUCCEEDED __carbon_SUCCEEDED -#define MAKE_HRESULT __carbon_MAKE_HRESULT -#define HRESULT __carbon_HRESULT -#define STDMETHODCALLTYPE __carbon_STDMETHODCALLTYPE -#include <IOKit/IOKitLib.h> -#include <IOKit/hid/IOHIDLib.h> -#include <ForceFeedback/ForceFeedback.h> -#undef ULONG -#undef E_INVALIDARG -#undef E_OUTOFMEMORY -#undef E_HANDLE -#undef E_ACCESSDENIED -#undef E_UNEXPECTED -#undef E_FAIL -#undef E_ABORT -#undef E_POINTER -#undef E_NOINTERFACE -#undef E_NOTIMPL -#undef S_FALSE -#undef S_OK -#undef HRESULT_FACILITY -#undef IS_ERROR -#undef FAILED -#undef SUCCEEDED -#undef MAKE_HRESULT -#undef HRESULT -#undef STDMETHODCALLTYPE -#undef DWORD -#undef LPDWORD -#undef LONG -#undef LPLONG -#undef E_PENDING -#endif /* HAVE_IOKIT_HID_IOHIDLIB_H */ - -#include "wine/debug.h" -#include "wine/unicode.h" -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" -#include "devguid.h" -#include "dinput.h" - -#include "dinput_private.h" -#include "device_private.h" -#include "joystick_private.h" - -#ifdef HAVE_IOHIDMANAGERCREATE - -WINE_DEFAULT_DEBUG_CHANNEL(dinput); - -#define MAKEUINT64(high, low) (((uint64_t)high << 32) | (uint32_t)low) - -static CFMutableArrayRef device_main_elements = NULL; - -/* Maps IOHIDDeviceRefs to CRITICAL_SECTION pointers. */ -static CFMutableDictionaryRef hid_device_crits = NULL; - -typedef struct JoystickImpl JoystickImpl; -static const IDirectInputDevice8WVtbl JoystickWvt; - -struct JoystickImpl -{ - struct JoystickGenericImpl generic; - - /* osx private */ - int id; - CFArrayRef elements; - int *element_values; - ObjProps **propmap; - FFDeviceObjectReference ff; - struct list effects; -}; - -static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) -{ - return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), - JoystickGenericImpl, base), JoystickImpl, generic); -} - -typedef struct _EffectImpl { - IDirectInputEffect IDirectInputEffect_iface; - LONG ref; - - JoystickImpl *device; - FFEffectObjectReference effect; - GUID guid; - - struct list entry; -} EffectImpl; - -static EffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface) -{ - return CONTAINING_RECORD(iface, EffectImpl, IDirectInputEffect_iface); -} - -static const IDirectInputEffectVtbl EffectVtbl; - -static const GUID DInput_Wine_OsX_Joystick_GUID = { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */ - 0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A} -}; - -static HRESULT osx_to_win32_hresult(HRESULT in) -{ - /* OSX returns 16-bit COM runtime errors, which we should - * convert to win32 */ - switch(in){ - case 0x80000001: - return E_NOTIMPL; - case 0x80000002: - return E_OUTOFMEMORY; - case 0x80000003: - return E_INVALIDARG; - case 0x80000004: - return E_NOINTERFACE; - case 0x80000005: - return E_POINTER; - case 0x80000006: - return E_HANDLE; - case 0x80000007: - return E_ABORT; - case 0x80000008: - return E_FAIL; - case 0x80000009: - return E_ACCESSDENIED; - case 0x8000FFFF: - return E_UNEXPECTED; - } - return in; -} - -static long get_device_property_long(IOHIDDeviceRef device, CFStringRef key) -{ - CFTypeRef ref; - long result = 0; - - if (device) - { - assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device)); - - ref = IOHIDDeviceGetProperty(device, key); - - if (ref && CFNumberGetTypeID() == CFGetTypeID(ref)) - CFNumberGetValue((CFNumberRef)ref, kCFNumberLongType, &result); - } - - return result; -} - -static CFStringRef copy_device_name(IOHIDDeviceRef device) -{ - CFStringRef name; - - if (device) - { - CFTypeRef ref_name; - - assert(IOHIDDeviceGetTypeID() == CFGetTypeID(device)); - - ref_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); - - if (ref_name && CFStringGetTypeID() == CFGetTypeID(ref_name)) - name = CFStringCreateCopy(kCFAllocatorDefault, ref_name); - else - { - long vendID, prodID; - - vendID = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); - prodID = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); - name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("0x%04lx 0x%04lx"), vendID, prodID); - } - } - else - { - ERR("NULL device\n"); - name = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("")); - } - - return name; -} - -static long get_device_location_ID(IOHIDDeviceRef device) -{ - return get_device_property_long(device, CFSTR(kIOHIDLocationIDKey)); -} - -static void copy_set_to_array(const void *value, void *context) -{ - CFArrayAppendValue(context, value); -} - -static CFComparisonResult device_name_comparator(IOHIDDeviceRef device1, IOHIDDeviceRef device2) -{ - CFStringRef name1 = copy_device_name(device1), name2 = copy_device_name(device2); - CFComparisonResult result = CFStringCompare(name1, name2, (kCFCompareForcedOrdering | kCFCompareNumerically)); - CFRelease(name1); - CFRelease(name2); - return result; -} - -static CFComparisonResult device_location_name_comparator(const void *val1, const void *val2, void *context) -{ - IOHIDDeviceRef device1 = (IOHIDDeviceRef)val1, device2 = (IOHIDDeviceRef)val2; - long loc1 = get_device_location_ID(device1), loc2 = get_device_location_ID(device2); - - if (loc1 < loc2) - return kCFCompareLessThan; - else if (loc1 > loc2) - return kCFCompareGreaterThan; - /* virtual joysticks may not have a kIOHIDLocationIDKey and will default to location ID of 0, this orders virtual joysticks by their name */ - return device_name_comparator(device1, device2); -} - -static const char* debugstr_cf(CFTypeRef t) -{ - CFStringRef s; - const char* ret; - - if (!t) return "(null)"; - - if (CFGetTypeID(t) == CFStringGetTypeID()) - s = t; - else - s = CFCopyDescription(t); - ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8); - if (ret) ret = debugstr_a(ret); - if (!ret) - { - const UniChar* u = CFStringGetCharactersPtr(s); - if (u) - ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s)); - } - if (!ret) - { - UniChar buf[200]; - int len = min(CFStringGetLength(s), ARRAY_SIZE(buf)); - CFStringGetCharacters(s, CFRangeMake(0, len), buf); - ret = debugstr_wn(buf, len); - } - if (s != t) CFRelease(s); - return ret; -} - -static const char* debugstr_device(IOHIDDeviceRef device) -{ - return wine_dbg_sprintf("<IOHIDDevice %p product %s IOHIDLocationID %lu>", device, - debugstr_cf(IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))), - get_device_location_ID(device)); -} - -static const char* debugstr_element(IOHIDElementRef element) -{ - return wine_dbg_sprintf("<IOHIDElement %p type %d usage %u/%u device %p>", element, - IOHIDElementGetType(element), IOHIDElementGetUsagePage(element), - IOHIDElementGetUsage(element), IOHIDElementGetDevice(element)); -} - -static IOHIDDeviceRef get_device_ref(int id) -{ - IOHIDElementRef device_main_element; - IOHIDDeviceRef hid_device; - - TRACE("id %d\n", id); - - if (!device_main_elements || id >= CFArrayGetCount(device_main_elements)) - return 0; - - device_main_element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements, id); - if (!device_main_element) - { - ERR("Invalid Element requested %i\n",id); - return 0; - } - - hid_device = IOHIDElementGetDevice(device_main_element); - if (!hid_device) - { - ERR("Invalid Device requested %i\n",id); - return 0; - } - - TRACE("-> %s\n", debugstr_device(hid_device)); - return hid_device; -} - -static HRESULT get_ff(IOHIDDeviceRef device, FFDeviceObjectReference *ret) -{ - io_service_t service; - CFMutableDictionaryRef matching; - CFTypeRef location_id; - HRESULT hr; - - TRACE("device %s\n", debugstr_device(device)); - - matching = IOServiceMatching(kIOHIDDeviceKey); - if(!matching){ - WARN("IOServiceMatching failed, force feedback disabled\n"); - return DIERR_DEVICENOTREG; - } - - location_id = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDLocationIDKey)); - if(!location_id){ - CFRelease(matching); - WARN("IOHIDDeviceGetProperty failed, force feedback disabled\n"); - return DIERR_DEVICENOTREG; - } - - CFDictionaryAddValue(matching, CFSTR(kIOHIDLocationIDKey), location_id); - - service = IOServiceGetMatchingService(kIOMasterPortDefault, matching); - - if (ret) - hr = osx_to_win32_hresult(FFCreateDevice(service, ret)); - else - hr = FFIsForceFeedback(service) == FF_OK ? S_OK : S_FALSE; - - IOObjectRelease(service); - TRACE("-> hr 0x%08x *ret %p\n", hr, ret ? *ret : NULL); - return hr; -} - -static CFMutableDictionaryRef create_osx_device_match(int usage) -{ - CFMutableDictionaryRef result; - - TRACE("usage %d\n", usage); - - result = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); - - if ( result ) - { - int number = kHIDPage_GenericDesktop; - CFNumberRef page = CFNumberCreate( kCFAllocatorDefault, - kCFNumberIntType, &number); - - if (page) - { - CFNumberRef cf_usage; - - CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsagePageKey ), page ); - CFRelease( page ); - - cf_usage = CFNumberCreate( kCFAllocatorDefault, - kCFNumberIntType, &usage); - if (cf_usage) - { - CFDictionarySetValue( result, CFSTR( kIOHIDDeviceUsageKey ), cf_usage ); - CFRelease( cf_usage ); - } - else - { - ERR("CFNumberCreate() failed.\n"); - CFRelease(result); - return NULL; - } - } - else - { - ERR("CFNumberCreate failed.\n"); - CFRelease(result); - return NULL; - } - } - else - { - ERR("CFDictionaryCreateMutable failed.\n"); - return NULL; - } - - return result; -} - -static CFIndex find_top_level(IOHIDDeviceRef hid_device, CFMutableArrayRef main_elements) -{ - CFArrayRef elements; - CFIndex total = 0; - - TRACE("hid_device %s\n", debugstr_device(hid_device)); - - if (!hid_device) - return 0; - - elements = IOHIDDeviceCopyMatchingElements(hid_device, NULL, 0); - - if (elements) - { - CFIndex idx, cnt = CFArrayGetCount(elements); - for (idx=0; idx<cnt; idx++) - { - IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, idx); - int type = IOHIDElementGetType(element); - - TRACE("element %s\n", debugstr_element(element)); - - /* Check for top-level gaming device collections */ - if (type == kIOHIDElementTypeCollection && IOHIDElementGetParent(element) == 0) - { - int usage_page = IOHIDElementGetUsagePage(element); - int usage = IOHIDElementGetUsage(element); - - if (usage_page == kHIDPage_GenericDesktop && - (usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad)) - { - CFArrayAppendValue(main_elements, element); - total++; - } - } - } - CFRelease(elements); - } - - TRACE("-> total %d\n", (int)total); - return total; -} - -static void get_element_children(IOHIDElementRef element, CFMutableArrayRef all_children) -{ - CFIndex idx, cnt; - CFArrayRef element_children = IOHIDElementGetChildren(element); - - TRACE("element %s\n", debugstr_element(element)); - - cnt = CFArrayGetCount(element_children); - - /* Either add the element to the array or grab its children */ - for (idx=0; idx<cnt; idx++) - { - IOHIDElementRef child; - - child = (IOHIDElementRef)CFArrayGetValueAtIndex(element_children, idx); - TRACE("child %s\n", debugstr_element(child)); - if (IOHIDElementGetType(child) == kIOHIDElementTypeCollection) - get_element_children(child, all_children); - else - CFArrayAppendValue(all_children, child); - } -} - -static int find_osx_devices(void) -{ - IOHIDManagerRef hid_manager; - CFMutableDictionaryRef result; - CFSetRef devset; - CFMutableArrayRef matching; - - TRACE("()\n"); - - hid_manager = IOHIDManagerCreate( kCFAllocatorDefault, 0L ); - if (IOHIDManagerOpen( hid_manager, 0 ) != kIOReturnSuccess) - { - ERR("Couldn't open IOHIDManager.\n"); - CFRelease( hid_manager ); - return 0; - } - - matching = CFArrayCreateMutable( kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks ); - - /* build matching dictionary */ - result = create_osx_device_match(kHIDUsage_GD_Joystick); - if (!result) - { - CFRelease(matching); - goto fail; - } - CFArrayAppendValue( matching, result ); - CFRelease( result ); - result = create_osx_device_match(kHIDUsage_GD_GamePad); - if (!result) - { - CFRelease(matching); - goto fail; - } - CFArrayAppendValue( matching, result ); - CFRelease( result ); - - IOHIDManagerSetDeviceMatchingMultiple( hid_manager, matching); - CFRelease( matching ); - devset = IOHIDManagerCopyDevices( hid_manager ); - if (devset) - { - CFIndex num_devices, num_main_elements, idx; - CFMutableArrayRef devices; - - num_devices = CFSetGetCount(devset); - devices = CFArrayCreateMutable(kCFAllocatorDefault, num_devices, &kCFTypeArrayCallBacks); - CFSetApplyFunction(devset, copy_set_to_array, devices); - CFRelease(devset); - CFArraySortValues(devices, CFRangeMake(0, num_devices), device_location_name_comparator, NULL); - - device_main_elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - hid_device_crits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); - if (!device_main_elements || !hid_device_crits) - { - if (device_main_elements) CFRelease(device_main_elements); - if (hid_device_crits) CFRelease(hid_device_crits); - CFRelease( devices ); - goto fail; - } - - num_main_elements = 0; - for (idx = 0; idx < num_devices; idx++) - { - CFIndex top; - IOHIDDeviceRef hid_device; - - hid_device = (IOHIDDeviceRef) CFArrayGetValueAtIndex(devices, idx); - TRACE("hid_device %s\n", debugstr_device(hid_device)); - top = find_top_level(hid_device, device_main_elements); - num_main_elements += top; - - if ( top ) { - /* This HID device has relevent elements, so it needs a critical section. */ - CRITICAL_SECTION *cs = HeapAlloc(GetProcessHeap(), 0, sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(cs); - cs->DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": hid_device_crits"); - - CFDictionaryAddValue(hid_device_crits, hid_device, cs); - } - } - - CFRelease(devices); - - TRACE("found %i device(s), %i collection(s)\n",(int)num_devices,(int)num_main_elements); - return (int)num_main_elements; - } - -fail: - IOHIDManagerClose( hid_manager, 0 ); - CFRelease( hid_manager ); - return 0; -} - -static int get_osx_device_name(int id, char *name, int length) -{ - CFStringRef str; - IOHIDDeviceRef hid_device; - - hid_device = get_device_ref(id); - - TRACE("id %d hid_device %s\n", id, debugstr_device(hid_device)); - - if (name) - name[0] = 0; - - if (!hid_device) - return 0; - - str = IOHIDDeviceGetProperty(hid_device, CFSTR( kIOHIDProductKey )); - if (str) - { - CFIndex len = CFStringGetLength(str); - if (length >= len) - { - CFStringGetCString(str,name,length,kCFStringEncodingASCII); - return len; - } - else - return (len+1); - } - return 0; -} - -static CFComparisonResult button_usage_comparator(const void *val1, const void *val2, void *context) -{ - IOHIDElementRef element1 = (IOHIDElementRef)val1, element2 = (IOHIDElementRef)val2; - int usage1 = IOHIDElementGetUsage(element1), usage2 = IOHIDElementGetUsage(element2); - - if (usage1 < usage2) - return kCFCompareLessThan; - if (usage1 > usage2) - return kCFCompareGreaterThan; - return kCFCompareEqualTo; -} - -static void get_osx_device_elements(JoystickImpl *device, uint64_t axis_map[8]) -{ - IOHIDElementRef device_main_element; - CFMutableArrayRef elements; - DWORD sliders = 0; - BOOL use_accel_brake_for_rx_ry = TRUE; - - TRACE("device %p device->id %d\n", device, device->id); - - device->elements = NULL; - - if (!device_main_elements || device->id >= CFArrayGetCount(device_main_elements)) - return; - - device_main_element = (IOHIDElementRef)CFArrayGetValueAtIndex(device_main_elements, device->id); - TRACE("device_main_element %s\n", debugstr_element(device_main_element)); - if (!device_main_element) - return; - - elements = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - get_element_children(device_main_element, elements); - - if (elements) - { - CFIndex idx, cnt = CFArrayGetCount( elements ); - CFMutableArrayRef axes = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFMutableArrayRef buttons = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - CFMutableArrayRef povs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - - /* Scan the elements to see if Rx/Ry is present, if not then Accelerator/Brake can be mapped to it. - * (Xbox One controller triggers use accelerator/brake) - */ - for ( idx = 0; idx < cnt; idx++ ) - { - IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elements, idx ); - IOHIDElementType type = IOHIDElementGetType( element ); - uint32_t usage_page = IOHIDElementGetUsagePage( element ); - uint32_t usage = IOHIDElementGetUsage( element ); - - if (type == kIOHIDElementTypeInput_Misc && usage_page == kHIDPage_GenericDesktop && - (usage == kHIDUsage_GD_Rx || usage == kHIDUsage_GD_Ry)) - { - use_accel_brake_for_rx_ry = FALSE; - } - } - - for ( idx = 0; idx < cnt; idx++ ) - { - IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elements, idx ); - int type = IOHIDElementGetType( element ); - int usage_page = IOHIDElementGetUsagePage( element ); - - TRACE("element %s\n", debugstr_element(element)); - - if (usage_page >= kHIDPage_VendorDefinedStart) - { - /* vendor pages can repurpose type ids, resulting in incorrect case matches below (e.g. ds4 controllers) */ - continue; - } - - switch(type) - { - case kIOHIDElementTypeInput_Button: - { - TRACE("kIOHIDElementTypeInput_Button usage_page %d\n", usage_page); - if ((usage_page != kHIDPage_Button) && (usage_page != kHIDPage_Consumer)) - { - /* avoid strange elements found on the 360 controller */ - continue; - } - - if (CFArrayGetCount(buttons) < 128) - CFArrayAppendValue(buttons, element); - break; - } - case kIOHIDElementTypeInput_Axis: - { - TRACE("kIOHIDElementTypeInput_Axis\n"); - CFArrayAppendValue(axes, element); - break; - } - case kIOHIDElementTypeInput_Misc: - { - uint32_t usage = IOHIDElementGetUsage( element ); - switch(MAKEUINT64(usage_page, usage)) - { - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Hatswitch): - { - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n"); - CFArrayAppendValue(povs, element); - break; - } - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Slider): - sliders ++; - if (sliders > 2) - break; - /* fallthrough, sliders are axis */ - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_X): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Y): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Z): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rx): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Ry): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rz): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Accelerator): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Brake): - { - if (usage == kHIDUsage_Sim_Accelerator || usage == kHIDUsage_Sim_Brake) - { - if (use_accel_brake_for_rx_ry) - TRACE("Using Sim_Accelerator/Brake for GD_Rx/Ry\n"); - else - break; - } - - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_* (%d)\n", usage); - axis_map[CFArrayGetCount(axes)]=MAKEUINT64(usage_page, usage); - CFArrayAppendValue(axes, element); - break; - } - default: - FIXME("kIOHIDElementTypeInput_Misc / Unhandled usage %i/%i\n", usage_page, usage); - } - break; - } - default: - FIXME("Unhandled type %i\n",type); - } - } - - /* Sort buttons into correct order */ - CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)), button_usage_comparator, NULL); - - device->generic.devcaps.dwAxes = CFArrayGetCount(axes); - device->generic.devcaps.dwButtons = CFArrayGetCount(buttons); - device->generic.devcaps.dwPOVs = CFArrayGetCount(povs); - - TRACE("axes %u povs %u buttons %u\n", device->generic.devcaps.dwAxes, device->generic.devcaps.dwPOVs, - device->generic.devcaps.dwButtons); - - /* build our element array in the order that dinput expects */ - CFArrayAppendArray(axes, povs, CFRangeMake(0, device->generic.devcaps.dwPOVs)); - CFArrayAppendArray(axes, buttons, CFRangeMake(0, device->generic.devcaps.dwButtons)); - device->elements = axes; - axes = NULL; - - CFRelease(povs); - CFRelease(buttons); - CFRelease(elements); - - device->element_values = HeapAlloc(GetProcessHeap(), 0, - CFArrayGetCount(device->elements) * sizeof(int)); - } - else - { - device->generic.devcaps.dwAxes = 0; - device->generic.devcaps.dwButtons = 0; - device->generic.devcaps.dwPOVs = 0; - } -} - -static void get_osx_device_elements_props(JoystickImpl *device) -{ - TRACE("device %p\n", device); - - if (device->elements) - { - CFIndex idx, cnt = CFArrayGetCount( device->elements ); - - for ( idx = 0; idx < cnt; idx++ ) - { - IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( device->elements, idx ); - - TRACE("element %s\n", debugstr_element(element)); - - device->generic.props[idx].lDevMin = IOHIDElementGetLogicalMin(element); - device->generic.props[idx].lDevMax = IOHIDElementGetLogicalMax(element); - device->generic.props[idx].lMin = 0; - device->generic.props[idx].lMax = 0xffff; - device->generic.props[idx].lDeadZone = 0; - device->generic.props[idx].lSaturation = 0; - } - } -} - -static IOReturn get_element_values(IOHIDDeviceRef hid_device, JoystickImpl *device) -{ - CFIndex i, element_count = CFArrayGetCount(device->elements); - IOReturn ret = kIOReturnSuccess; - IOHIDElementRef element; - IOHIDValueRef valueRef; - - /* If more than one thread is trying to poll the same HID device, we can - * crash deep inside IOKit. So we enter a per-IOHIDDevice critical section - * here. Note that it must be per-HID device and not just per-JoystickImpl, - * as there may be multiple JoystickImpls referencing the same underlying - * device. */ - - CRITICAL_SECTION *crit = (CRITICAL_SECTION *)CFDictionaryGetValue(hid_device_crits, hid_device); - if (!crit) { - ERR("missing critical section for device %s\n", debugstr_device(hid_device)); - return kIOReturnError; - } - - EnterCriticalSection(crit); - - for (i = 0; i < element_count; i++) - { - element = (IOHIDElementRef)CFArrayGetValueAtIndex(device->elements, i); - ret = IOHIDDeviceGetValue(hid_device, element, &valueRef); - if (ret != kIOReturnSuccess) - { - ERR("error getting value of element %s: %08x\n", debugstr_element(element), ret); - break; - } - - device->element_values[i] = IOHIDValueGetIntegerValue(valueRef); - } - - LeaveCriticalSection(crit); - return ret; -} - -static void poll_osx_device_state( IDirectInputDevice8W *iface ) -{ - JoystickImpl *device = impl_from_IDirectInputDevice8W( iface ); - IOHIDElementRef device_main_element; - IOHIDDeviceRef hid_device; - - TRACE("device %p device->id %i\n", device, device->id); - - if (!device_main_elements || device->id >= CFArrayGetCount(device_main_elements)) - return; - - device_main_element = (IOHIDElementRef) CFArrayGetValueAtIndex(device_main_elements, device->id); - hid_device = IOHIDElementGetDevice(device_main_element); - TRACE("main element %s hid_device %s\n", debugstr_element(device_main_element), debugstr_device(hid_device)); - if (!hid_device) - return; - - if (device->elements) - { - if (get_element_values(hid_device, device) != kIOReturnSuccess) - return; - - int button_idx = 0; - int pov_idx = 0; - int slider_idx = 0; - int inst_id; - CFIndex idx, cnt = CFArrayGetCount( device->elements ); - - for ( idx = 0; idx < cnt; idx++ ) - { - int oldVal, newVal, val = device->element_values[idx]; - IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( device->elements, idx ); - int type = IOHIDElementGetType( element ); - - TRACE("element %s\n", debugstr_element(element)); - - switch(type) - { - case kIOHIDElementTypeInput_Button: - TRACE("kIOHIDElementTypeInput_Button\n"); - if(button_idx < 128) - { - newVal = val ? 0x80 : 0x0; - oldVal = device->generic.js.rgbButtons[button_idx]; - device->generic.js.rgbButtons[button_idx] = newVal; - TRACE("val %d oldVal %d newVal %d\n", val, oldVal, newVal); - if (oldVal != newVal) - { - inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON; - queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++); - if (device->generic.base.hEvent) - SetEvent( device->generic.base.hEvent ); - } - button_idx ++; - } - break; - case kIOHIDElementTypeInput_Misc: - { - uint32_t usage_page = IOHIDElementGetUsagePage( element ); - uint32_t usage = IOHIDElementGetUsage( element ); - switch(MAKEUINT64(usage_page, usage)) - { - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Hatswitch): - { - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n"); - oldVal = device->generic.js.rgdwPOV[pov_idx]; - if ((val > device->generic.props[idx].lDevMax) || (val < device->generic.props[idx].lDevMin)) - newVal = -1; - else - newVal = (val - device->generic.props[idx].lDevMin) * 4500; - device->generic.js.rgdwPOV[pov_idx] = newVal; - TRACE("val %d oldVal %d newVal %d\n", val, oldVal, newVal); - if (oldVal != newVal) - { - inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV; - queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++); - if (device->generic.base.hEvent) - SetEvent( device->generic.base.hEvent ); - } - pov_idx ++; - break; - } - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_X): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Y): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Z): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rx): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Ry): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rz): - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Slider): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Accelerator): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Brake): - { - int wine_obj = -1; - - newVal = joystick_map_axis(&device->generic.props[idx], val); - switch (MAKEUINT64(usage_page, usage)) - { - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_X): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_X\n"); - wine_obj = 0; - oldVal = device->generic.js.lX; - device->generic.js.lX = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Y): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Y\n"); - wine_obj = 1; - oldVal = device->generic.js.lY; - device->generic.js.lY = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Z): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Z\n"); - wine_obj = 2; - oldVal = device->generic.js.lZ; - device->generic.js.lZ = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rx): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Accelerator): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rx\n"); - wine_obj = 3; - oldVal = device->generic.js.lRx; - device->generic.js.lRx = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Ry): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Brake): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Ry\n"); - wine_obj = 4; - oldVal = device->generic.js.lRy; - device->generic.js.lRy = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rz): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rz\n"); - wine_obj = 5; - oldVal = device->generic.js.lRz; - device->generic.js.lRz = newVal; - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Slider): - TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider\n"); - wine_obj = 6 + slider_idx; - oldVal = device->generic.js.rglSlider[slider_idx]; - device->generic.js.rglSlider[slider_idx] = newVal; - slider_idx ++; - break; - } - TRACE("val %d oldVal %d newVal %d\n", val, oldVal, newVal); - if ((wine_obj != -1) && - (oldVal != newVal)) - { - inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS; - queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++); - if (device->generic.base.hEvent) - SetEvent( device->generic.base.hEvent ); - } - - break; - } - default: - FIXME("kIOHIDElementTypeInput_Misc / unhandled usage %i\n", usage); - } - break; - } - default: - FIXME("Unhandled type %i\n",type); - } - } - } -} - -static INT find_joystick_devices(void) -{ - static INT joystick_devices_count = -1; - - if (joystick_devices_count != -1) return joystick_devices_count; - - joystick_devices_count = find_osx_devices(); - - return joystick_devices_count; -} - -static DWORD make_vid_pid(IOHIDDeviceRef device) -{ - long vendID, prodID; - - vendID = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); - prodID = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); - - return MAKELONG(vendID, prodID); -} - -static HRESULT joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) -{ - char name[MAX_PATH]; - char friendly[32]; - IOHIDDeviceRef device; - BOOL is_joystick; - - TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id); - - if (id >= find_joystick_devices()) return E_FAIL; - - device = get_device_ref(id); - - if ((dwDevType == 0) || - ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) || - (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) { - - if (dwFlags & DIEDFL_FORCEFEEDBACK) { - if(!device) - return S_FALSE; - if(get_ff(device, NULL) != S_OK) - return S_FALSE; - } - is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick; - /* Return joystick */ - lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID; - lpddi->guidInstance.Data3 = id; - lpddi->guidProduct = dinput_pidvid_guid; - lpddi->guidProduct.Data1 = make_vid_pid(device); - lpddi->dwDevType = get_device_type(version, is_joystick); - lpddi->dwDevType |= DIDEVTYPE_HID; - lpddi->wUsagePage = 0x01; /* Desktop */ - if (is_joystick) - lpddi->wUsage = 0x04; /* Joystick */ - else - lpddi->wUsage = 0x05; /* Game Pad */ - sprintf(friendly, "Joystick %d", id); - MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH); - - /* get the device name */ - get_osx_device_name(id, name, MAX_PATH); - - MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH); - lpddi->guidFFDriver = GUID_NULL; - return S_OK; - } - - return S_FALSE; -} - -static const char *osx_ff_axis_name(UInt8 axis) -{ - static char ret[6]; - switch(axis){ - case FFJOFS_X: - return "FFJOFS_X"; - case FFJOFS_Y: - return "FFJOFS_Y"; - case FFJOFS_Z: - return "FFJOFS_Z"; - } - sprintf(ret, "%u", (unsigned int)axis); - return ret; -} - -static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps, UInt8 axis) -{ - int i; - for(i = 0; i < ffcaps->numFfAxes; ++i) - if(ffcaps->ffAxes[i] == axis) - return TRUE; - return FALSE; -} - -static HRESULT alloc_device( REFGUID rguid, IDirectInputImpl *dinput, JoystickImpl **out, unsigned short index ) -{ - DWORD i; - IOHIDDeviceRef device; - JoystickImpl* newDevice; - char name[MAX_PATH]; - HRESULT hr; - LPDIDATAFORMAT df = NULL; - int idx = 0; - uint64_t axis_map[8]; /* max axes */ - int slider_count = 0; - FFCAPABILITIES ffcaps; - - TRACE( "%s %p %p %hu\n", debugstr_guid( rguid ), dinput, out, index ); - - if (FAILED(hr = direct_input_device_alloc( sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice ))) - return hr; - df = newDevice->generic.base.data_format.wine_df; - newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit"); - - newDevice->id = index; - - device = get_device_ref(index); - - newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID; - newDevice->generic.guidInstance.Data3 = index; - newDevice->generic.guidProduct = dinput_pidvid_guid; - newDevice->generic.guidProduct.Data1 = make_vid_pid(device); - newDevice->generic.joy_polldev = poll_osx_device_state; - - /* get the device name */ - get_osx_device_name(index, name, MAX_PATH); - TRACE("Name %s\n",name); - - /* copy the device name */ - newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1); - strcpy(newDevice->generic.name, name); - - list_init(&newDevice->effects); - if(get_ff(device, &newDevice->ff) == S_OK){ - newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK; - - hr = FFDeviceGetForceFeedbackCapabilities(newDevice->ff, &ffcaps); - if(SUCCEEDED(hr)){ - TRACE("FF Capabilities:\n"); - TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps.supportedEffects); - TRACE("\temulatedEffects: 0x%x\n", (unsigned int)ffcaps.emulatedEffects); - TRACE("\tsubType: 0x%x\n", (unsigned int)ffcaps.subType); - TRACE("\tnumFfAxes: %u\n", (unsigned int)ffcaps.numFfAxes); - TRACE("\tffAxes: ["); - for(i = 0; i < ffcaps.numFfAxes; ++i){ - TRACE("%s", osx_ff_axis_name(ffcaps.ffAxes[i])); - if(i < ffcaps.numFfAxes - 1) - TRACE(", "); - } - TRACE("]\n"); - TRACE("\tstorageCapacity: %u\n", (unsigned int)ffcaps.storageCapacity); - TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps.playbackCapacity); - } - - hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_RESET); - if(FAILED(hr)) - WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr); - - hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_SETACTUATORSON); - if(FAILED(hr)) - WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr); - } - - memset(axis_map, 0, sizeof(axis_map)); - get_osx_device_elements(newDevice, axis_map); - - TRACE("%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs); - - if (newDevice->generic.devcaps.dwButtons > 128) - { - WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons); - newDevice->generic.devcaps.dwButtons = 128; - } - - /* Create copy of default data format */ - memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize); - - df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons; - if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED; - - for (i = 0; i < newDevice->generic.devcaps.dwAxes; i++) - { - int wine_obj = -1; - BOOL has_ff = FALSE; - switch (axis_map[i]) - { - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_X): - wine_obj = 0; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_X); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Y): - wine_obj = 1; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Y); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Z): - wine_obj = 2; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Z); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rx): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Accelerator): - wine_obj = 3; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RX); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Ry): - case MAKEUINT64(kHIDPage_Simulation, kHIDUsage_Sim_Brake): - wine_obj = 4; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RY); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Rz): - wine_obj = 5; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RZ); - break; - case MAKEUINT64(kHIDPage_GenericDesktop, kHIDUsage_GD_Slider): - wine_obj = 6 + slider_count; - has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_SLIDER(slider_count)); - slider_count++; - break; - } - if (wine_obj < 0 ) continue; - - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize); - df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS; - if(has_ff) - df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR; - ++idx; - } - - for (i = 0; i < newDevice->generic.devcaps.dwPOVs; i++) - { - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 8], df->dwObjSize); - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV; - } - - for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++) - { - memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize); - df->rgodf[idx ].pguid = &GUID_Button; - df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON; - } - - /* initialize default properties */ - get_osx_device_elements_props(newDevice); - - newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps); - newDevice->generic.devcaps.dwFlags |= DIDC_ATTACHED; - if (newDevice->generic.base.dinput->dwVersion >= 0x0800) - newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - newDevice->generic.devcaps.dwFFSamplePeriod = 0; - newDevice->generic.devcaps.dwFFMinTimeResolution = 0; - newDevice->generic.devcaps.dwFirmwareRevision = 0; - newDevice->generic.devcaps.dwHardwareRevision = 0; - newDevice->generic.devcaps.dwFFDriverVersion = 0; - - if (TRACE_ON(dinput)) { - TRACE("allocated device %p\n", newDevice); - _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df); - _dump_DIDEVCAPS(&newDevice->generic.devcaps); - } - - *out = newDevice; - return DI_OK; - -FAILED: - hr = DIERR_OUTOFMEMORY; - if (newDevice->ff) FFReleaseDevice(newDevice->ff); - if (newDevice->elements) CFRelease(newDevice->elements); - if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); - HeapFree(GetProcessHeap(), 0, df); - release_DataFormat(&newDevice->generic.base.data_format); - HeapFree(GetProcessHeap(),0,newDevice->generic.name); - HeapFree(GetProcessHeap(),0,newDevice); - return hr; -} - -/****************************************************************************** - * get_joystick_index : Get the joystick index from a given GUID - */ -static unsigned short get_joystick_index(REFGUID guid) -{ - GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID; - GUID dev_guid = *guid; - GUID prod_guid = *guid; - IOHIDDeviceRef device; - int joystick_devices_count; - INT i; - - wine_joystick.Data3 = 0; - dev_guid.Data3 = 0; - - /* for the standard joystick GUID use index 0 */ - if(IsEqualGUID(&GUID_Joystick,guid)) return 0; - - /* for the wine joystick GUIDs use the index stored in Data3 */ - if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3; - - prod_guid.Data1 = 0; - if(IsEqualGUID(&dinput_pidvid_guid, &prod_guid)) - { - joystick_devices_count = find_joystick_devices(); - for(i = 0; i < joystick_devices_count; i++) - { - device = get_device_ref(i); - if(guid->Data1 == make_vid_pid(device)) - return i; - } - } - - return 0xffff; -} - -static HRESULT joydev_create_device( IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDevice8W **out ) -{ - unsigned short index; - int joystick_devices_count; - - TRACE( "%p %s %p\n", dinput, debugstr_guid( rguid ), out ); - *out = NULL; - - if ((joystick_devices_count = find_joystick_devices()) == 0) - return DIERR_DEVICENOTREG; - - if ((index = get_joystick_index(rguid)) < 0xffff && - joystick_devices_count && index < joystick_devices_count) - { - JoystickImpl *This; - HRESULT hr; - - if (FAILED(hr = alloc_device( rguid, dinput, &This, index ))) return hr; - - TRACE( "Created a Joystick device (%p)\n", This ); - - *out = &This->generic.base.IDirectInputDevice8W_iface; - return hr; - } - - return DIERR_DEVICENOTREG; -} - -static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); - _dump_DIPROPHEADER(pdiph); - - if (!IS_DIPROP(rguid)) return DI_OK; - - switch (LOWORD(rguid)) { - case (DWORD_PTR) DIPROP_GUIDANDPATH: - { - static const WCHAR formatW[] = {'\','\','?','\','h','i','d','#','v','i','d','_','%','0','4','x','&', - 'p','i','d','_','%','0','4','x','&','%','s','_','%','i',0}; - static const WCHAR miW[] = {'m','i',0}; - static const WCHAR igW[] = {'i','g',0}; - - BOOL is_gamepad; - IOHIDDeviceRef device = get_device_ref(This->id); - LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph; - WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey)); - WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey)); - - if (!pid || !vid) - return DIERR_UNSUPPORTED; - - is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid); - pd->guidClass = GUID_DEVCLASS_HIDCLASS; - sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, This->id); - - TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath)); - break; - } - - default: - return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph); - } - - return DI_OK; -} - -static HRESULT osx_set_autocenter(JoystickImpl *This, - const DIPROPDWORD *header) -{ - UInt32 v; - HRESULT hr; - if(!This->ff) - return DIERR_UNSUPPORTED; - v = header->dwData; - hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This->ff, FFPROP_AUTOCENTER, &v)); - TRACE("returning: %08x\n", hr); - return hr; -} - -static HRESULT osx_set_ffgain(JoystickImpl *This, const DIPROPDWORD *header) -{ - UInt32 v; - HRESULT hr; - if(!This->ff) - return DIERR_UNSUPPORTED; - v = header->dwData; - hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This->ff, FFPROP_FFGAIN, &v)); - TRACE("returning: %08x\n", hr); - return hr; -} - -static HRESULT WINAPI JoystickWImpl_SetProperty(IDirectInputDevice8W *iface, - const GUID *prop, const DIPROPHEADER *header) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - - TRACE("%p %s %p\n", This, debugstr_guid(prop), header); - - switch(LOWORD(prop)) - { - case (DWORD_PTR)DIPROP_AUTOCENTER: - return osx_set_autocenter(This, (const DIPROPDWORD *)header); - case (DWORD_PTR)DIPROP_FFGAIN: - return osx_set_ffgain(This, (const DIPROPDWORD *)header); - } - - return JoystickWGenericImpl_SetProperty(iface, prop, header); -} - -static CFUUIDRef effect_win_to_mac(const GUID *effect) -{ -#define DO_MAP(X) \ - if(IsEqualGUID(&GUID_##X, effect)) \ - return kFFEffectType_##X##_ID; - DO_MAP(ConstantForce) - DO_MAP(RampForce) - DO_MAP(Square) - DO_MAP(Sine) - DO_MAP(Triangle) - DO_MAP(SawtoothUp) - DO_MAP(SawtoothDown) - DO_MAP(Spring) - DO_MAP(Damper) - DO_MAP(Inertia) - DO_MAP(Friction) - DO_MAP(CustomForce) -#undef DO_MAP - WARN("Unknown effect GUID! %s\n", debugstr_guid(effect)); - return 0; -} - -static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface, - const GUID *type, const DIEFFECT *params, IDirectInputEffect **out, - IUnknown *outer) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - EffectImpl *effect; - HRESULT hr; - - TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer); - dump_DIEFFECT(params, type, 0); - - if(!This->ff){ - TRACE("No force feedback support\n"); - *out = NULL; - return DIERR_UNSUPPORTED; - } - - if(outer) - WARN("aggregation not implemented\n"); - - effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); - effect->IDirectInputEffect_iface.lpVtbl = &EffectVtbl; - effect->ref = 1; - effect->guid = *type; - effect->device = This; - - /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */ - hr = osx_to_win32_hresult(FFDeviceCreateEffect(This->ff, - effect_win_to_mac(type), (FFEFFECT*)params, &effect->effect)); - if(FAILED(hr)){ - WARN("FFDeviceCreateEffect failed: %08x\n", hr); - HeapFree(GetProcessHeap(), 0, effect); - return hr; - } - - list_add_tail(&This->effects, &effect->entry); - *out = &effect->IDirectInputEffect_iface; - - TRACE("allocated effect: %p\n", effect); - - return S_OK; -} - -static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W *iface, - DWORD flags) -{ - JoystickImpl *This = impl_from_IDirectInputDevice8W(iface); - HRESULT hr; - - TRACE("%p 0x%x\n", This, flags); - - if(!This->ff) - return DI_NOEFFECT; - - hr = osx_to_win32_hresult(FFDeviceSendForceFeedbackCommand(This->ff, flags)); - if(FAILED(hr)){ - WARN("FFDeviceSendForceFeedbackCommand failed: %08x\n", hr); - return hr; - } - - return S_OK; -} - -const struct dinput_device joystick_osx_device = { - "Wine OS X joystick driver", - joydev_enum_device, - joydev_create_device -}; - -static const IDirectInputDevice8WVtbl JoystickWvt = -{ - IDirectInputDevice2WImpl_QueryInterface, - IDirectInputDevice2WImpl_AddRef, - JoystickWGenericImpl_Release, - JoystickWGenericImpl_GetCapabilities, - IDirectInputDevice2WImpl_EnumObjects, - JoystickWImpl_GetProperty, - JoystickWImpl_SetProperty, - IDirectInputDevice2WImpl_Acquire, - IDirectInputDevice2WImpl_Unacquire, - JoystickWGenericImpl_GetDeviceState, - IDirectInputDevice2WImpl_GetDeviceData, - IDirectInputDevice2WImpl_SetDataFormat, - IDirectInputDevice2WImpl_SetEventNotification, - IDirectInputDevice2WImpl_SetCooperativeLevel, - JoystickWGenericImpl_GetObjectInfo, - JoystickWGenericImpl_GetDeviceInfo, - IDirectInputDevice2WImpl_RunControlPanel, - IDirectInputDevice2WImpl_Initialize, - JoystickWImpl_CreateEffect, - IDirectInputDevice2WImpl_EnumEffects, - IDirectInputDevice2WImpl_GetEffectInfo, - IDirectInputDevice2WImpl_GetForceFeedbackState, - JoystickWImpl_SendForceFeedbackCommand, - IDirectInputDevice2WImpl_EnumCreatedEffectObjects, - IDirectInputDevice2WImpl_Escape, - JoystickWGenericImpl_Poll, - IDirectInputDevice2WImpl_SendDeviceData, - IDirectInputDevice7WImpl_EnumEffectsInFile, - IDirectInputDevice7WImpl_WriteEffectToFile, - JoystickWGenericImpl_BuildActionMap, - JoystickWGenericImpl_SetActionMap, - IDirectInputDevice8WImpl_GetImageInfo -}; - -static HRESULT WINAPI effect_QueryInterface(IDirectInputEffect *iface, - const GUID *guid, void **out) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - - TRACE("%p %s %p\n", This, debugstr_guid(guid), out); - - if(IsEqualIID(guid, &IID_IUnknown) || IsEqualIID(guid, &IID_IDirectInputEffect)){ - *out = iface; - IDirectInputEffect_AddRef(iface); - return S_OK; - } - - return E_NOINTERFACE; -} - -static ULONG WINAPI effect_AddRef(IDirectInputEffect *iface) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE("%p, ref is now: %u\n", This, ref); - return ref; -} - -static ULONG WINAPI effect_Release(IDirectInputEffect *iface) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - ULONG ref = InterlockedDecrement(&This->ref); - TRACE("%p, ref is now: %u\n", This, ref); - - if(!ref){ - list_remove(&This->entry); - FFDeviceReleaseEffect(This->device->ff, This->effect); - HeapFree(GetProcessHeap(), 0, This); - } - - return ref; -} - -static HRESULT WINAPI effect_Initialize(IDirectInputEffect *iface, HINSTANCE hinst, - DWORD version, const GUID *guid) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p 0x%x, %s\n", This, hinst, version, debugstr_guid(guid)); - return S_OK; -} - -static HRESULT WINAPI effect_GetEffectGuid(IDirectInputEffect *iface, GUID *out) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p\n", This, out); - *out = This->guid; - return S_OK; -} - -static HRESULT WINAPI effect_GetParameters(IDirectInputEffect *iface, - DIEFFECT *effect, DWORD flags) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p 0x%x\n", This, effect, flags); - return osx_to_win32_hresult(FFEffectGetParameters(This->effect, (FFEFFECT*)effect, flags)); -} - -static HRESULT WINAPI effect_SetParameters(IDirectInputEffect *iface, - const DIEFFECT *effect, DWORD flags) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p 0x%x\n", This, effect, flags); - dump_DIEFFECT(effect, &This->guid, flags); - return osx_to_win32_hresult(FFEffectSetParameters(This->effect, (FFEFFECT*)effect, flags)); -} - -static HRESULT WINAPI effect_Start(IDirectInputEffect *iface, DWORD iterations, - DWORD flags) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p 0x%x 0x%x\n", This, iterations, flags); - return osx_to_win32_hresult(FFEffectStart(This->effect, iterations, flags)); -} - -static HRESULT WINAPI effect_Stop(IDirectInputEffect *iface) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p\n", This); - return osx_to_win32_hresult(FFEffectStop(This->effect)); -} - -static HRESULT WINAPI effect_GetEffectStatus(IDirectInputEffect *iface, DWORD *flags) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p\n", This, flags); - return osx_to_win32_hresult(FFEffectGetEffectStatus(This->effect, (UInt32*)flags)); -} - -static HRESULT WINAPI effect_Download(IDirectInputEffect *iface) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p\n", This); - return osx_to_win32_hresult(FFEffectDownload(This->effect)); -} - -static HRESULT WINAPI effect_Unload(IDirectInputEffect *iface) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p\n", This); - return osx_to_win32_hresult(FFEffectUnload(This->effect)); -} - -static HRESULT WINAPI effect_Escape(IDirectInputEffect *iface, DIEFFESCAPE *escape) -{ - EffectImpl *This = impl_from_IDirectInputEffect(iface); - TRACE("%p %p\n", This, escape); - return osx_to_win32_hresult(FFEffectEscape(This->effect, (FFEFFESCAPE*)escape)); -} - -static const IDirectInputEffectVtbl EffectVtbl = { - effect_QueryInterface, - effect_AddRef, - effect_Release, - effect_Initialize, - effect_GetEffectGuid, - effect_GetParameters, - effect_SetParameters, - effect_Start, - effect_Stop, - effect_GetEffectStatus, - effect_Download, - effect_Unload, - effect_Escape -}; - -#else /* HAVE_IOHIDMANAGERCREATE */ - -const struct dinput_device joystick_osx_device = { - "Wine OS X joystick driver", - NULL, - NULL, -}; - -#endif /* HAVE_IOHIDMANAGERCREATE */ diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h deleted file mode 100644 index 32265edef03..00000000000 --- a/dlls/dinput/joystick_private.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2009, Aric Stewart, 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 - */ - -#ifndef __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H -#define __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H - -#include <stdarg.h> - -#include "windef.h" -#include "winbase.h" -#include "dinput.h" -#include "wine/list.h" -#include "wine/unicode.h" -#include "dinput_private.h" -#include "device_private.h" - -/* Number of objects in the default data format */ -#define MAX_PROPS 164 -struct JoystickGenericImpl; - -typedef void joy_polldev_handler( IDirectInputDevice8W *iface ); - -typedef struct JoystickGenericImpl -{ - struct IDirectInputDeviceImpl base; - - ObjProps props[MAX_PROPS]; - DIDEVCAPS devcaps; - DIJOYSTATE2 js; /* wine data */ - GUID guidProduct; - GUID guidInstance; - char *name; - int device_axis_count; /* Total number of axes in the device */ - int *axis_map; /* User axes remapping */ - LONG deadzone; /* Default dead-zone */ - - joy_polldev_handler *joy_polldev; -} JoystickGenericImpl; - -LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN; -HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map) DECLSPEC_HIDDEN; - -DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN; - -BOOL device_disabled_registry(const char* name) DECLSPEC_HIDDEN; -BOOL device_instance_is_disabled( DIDEVICEINSTANCEW *instance, BOOL *override ) DECLSPEC_HIDDEN; - -ULONG WINAPI JoystickWGenericImpl_Release(LPDIRECTINPUTDEVICE8W iface); - -HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, - LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) DECLSPEC_HIDDEN; - -void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo( LPDIRECTINPUTDEVICE8W iface, - LPDIDEVICEINSTANCEW pdidi) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN; - -HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN; - -DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN; -void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN; -BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) DECLSPEC_HIDDEN; - -#endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */ diff --git a/dlls/dinput8/Makefile.in b/dlls/dinput8/Makefile.in index 23017cb5983..1d3574aa1a0 100644 --- a/dlls/dinput8/Makefile.in +++ b/dlls/dinput8/Makefile.in @@ -2,7 +2,6 @@ MODULE = dinput8.dll IMPORTLIB = dinput8 IMPORTS = dinput8 dxguid uuid comctl32 ole32 user32 advapi32 hid setupapi EXTRADEFS = -DDIRECTINPUT_VERSION=0x0800 -EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS) PARENTSRC = ../dinput
EXTRADLLFLAGS = -mcygwin @@ -13,12 +12,7 @@ C_SRCS = \ data_formats.c \ device.c \ dinput_main.c \ - effect_linuxinput.c \ - joystick.c \ joystick_hid.c \ - joystick_linux.c \ - joystick_linuxinput.c \ - joystick_osx.c \ keyboard.c \ mouse.c