diff --git a/reactos/lib/dinput/device.c b/reactos/lib/dinput/device.c
index 6139e53daed..a38dea64a5d 100644
--- a/reactos/lib/dinput/device.c
+++ b/reactos/lib/dinput/device.c
@@ -464,7 +464,7 @@ HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags
) {
IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
- TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
+ TRACE("(this=%p,%p,0x%08lx)\n",This,hwnd,dwflags);
if (TRACE_ON(dinput)) {
TRACE(" cooperative level : ");
_dump_cooperativelevel_DI(dwflags);
@@ -476,7 +476,7 @@ HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
LPDIRECTINPUTDEVICE8A iface,HANDLE hnd
) {
IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
- FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
+ FIXME("(this=%p,%p): stub\n",This,hnd);
return DI_OK;
}
diff --git a/reactos/lib/dinput/device_private.h b/reactos/lib/dinput/device_private.h
index e7a32096efa..4f2347bcb6f 100644
--- a/reactos/lib/dinput/device_private.h
+++ b/reactos/lib/dinput/device_private.h
@@ -30,8 +30,8 @@
typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
struct IDirectInputDevice2AImpl
{
- IDirectInputDevice2AVtbl *lpVtbl;
- DWORD ref;
+ const IDirectInputDevice2AVtbl *lpVtbl;
+ LONG ref;
GUID guid;
};
diff --git a/reactos/lib/dinput/dinput.spec b/reactos/lib/dinput/dinput.spec
index 9a5ec99fd43..619079526c6 100644
--- a/reactos/lib/dinput/dinput.spec
+++ b/reactos/lib/dinput/dinput.spec
@@ -1,7 +1,7 @@
-@ stdcall DirectInputCreateA(long long ptr ptr)
-@ stdcall DirectInputCreateW(long long ptr ptr)
-@ stdcall DirectInputCreateEx(long long ptr ptr ptr)
-@ stdcall -private DllCanUnloadNow() DINPUT_DllCanUnloadNow
-@ stdcall -private DllGetClassObject(ptr ptr ptr) DINPUT_DllGetClassObject
-@ stdcall -private DllRegisterServer() DINPUT_DllRegisterServer
-@ stdcall -private DllUnregisterServer() DINPUT_DllUnregisterServer
+@ stdcall DirectInputCreateA(long long ptr ptr)
+@ stdcall DirectInputCreateEx(long long ptr ptr ptr)
+@ stdcall DirectInputCreateW(long long ptr ptr)
+@ stdcall -private DllCanUnloadNow()
+@ stdcall -private DllGetClassObject(ptr ptr ptr)
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/reactos/lib/dinput/dinput.xml b/reactos/lib/dinput/dinput.xml
index 9f96816e446..1cc8712c116 100644
--- a/reactos/lib/dinput/dinput.xml
+++ b/reactos/lib/dinput/dinput.xml
@@ -21,6 +21,7 @@
data_formats.c
device.c
dinput_main.c
+ effect_linuxinput.c
joystick_linux.c
joystick_linuxinput.c
keyboard.c
diff --git a/reactos/lib/dinput/dinput_main.c b/reactos/lib/dinput/dinput_main.c
index 74f0ddf8877..cc12e7a22c2 100644
--- a/reactos/lib/dinput/dinput_main.c
+++ b/reactos/lib/dinput/dinput_main.c
@@ -46,10 +46,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
-static IDirectInput7AVtbl ddi7avt;
-static IDirectInput7WVtbl ddi7wvt;
-static IDirectInput8AVtbl ddi8avt;
-static IDirectInput8WVtbl ddi8wvt;
+static const IDirectInput7AVtbl ddi7avt;
+static const IDirectInput7WVtbl ddi7wvt;
+static const IDirectInput8AVtbl ddi8avt;
+static const IDirectInput8WVtbl ddi8wvt;
static const struct dinput_device *dinput_devices[] =
{
@@ -86,7 +86,7 @@ HRESULT WINAPI DirectInputCreateEx(
{
IDirectInputImpl* This;
- TRACE("(0x%08lx,%04lx,%s,%p,%p)\n", (DWORD)hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);
+ TRACE("(%p,%04lx,%s,%p,%p)\n", hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);
if (IsEqualGUID(&IID_IDirectInputA,riid) ||
IsEqualGUID(&IID_IDirectInput2A,riid) ||
@@ -384,7 +384,7 @@ static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
HWND hwndOwner,
DWORD dwFlags) {
IDirectInputImpl *This = (IDirectInputImpl *)iface;
- FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
+ FIXME("(%p)->(%p,%08lx): stub\n",This, hwndOwner, dwFlags);
return DI_OK;
}
@@ -535,7 +535,7 @@ static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
# define XCAST(fun) (void*)
#endif
-static IDirectInput7AVtbl ddi7avt = {
+static const IDirectInput7AVtbl ddi7avt = {
XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,
XCAST(AddRef)IDirectInputAImpl_AddRef,
XCAST(Release)IDirectInputAImpl_Release,
@@ -555,7 +555,7 @@ static IDirectInput7AVtbl ddi7avt = {
# define XCAST(fun) (void*)
#endif
-static IDirectInput7WVtbl ddi7wvt = {
+static const IDirectInput7WVtbl ddi7wvt = {
XCAST(QueryInterface)IDirectInputWImpl_QueryInterface,
XCAST(AddRef)IDirectInputAImpl_AddRef,
XCAST(Release)IDirectInputAImpl_Release,
@@ -575,7 +575,7 @@ static IDirectInput7WVtbl ddi7wvt = {
# define XCAST(fun) (void*)
#endif
-static IDirectInput8AVtbl ddi8avt = {
+static const IDirectInput8AVtbl ddi8avt = {
XCAST(QueryInterface)IDirectInput8AImpl_QueryInterface,
XCAST(AddRef)IDirectInputAImpl_AddRef,
XCAST(Release)IDirectInputAImpl_Release,
@@ -595,7 +595,7 @@ static IDirectInput8AVtbl ddi8avt = {
#else
# define XCAST(fun) (void*)
#endif
-static IDirectInput8WVtbl ddi8wvt = {
+static const IDirectInput8WVtbl ddi8wvt = {
XCAST(QueryInterface)IDirectInput8WImpl_QueryInterface,
XCAST(AddRef)IDirectInputAImpl_AddRef,
XCAST(Release)IDirectInputAImpl_Release,
@@ -616,8 +616,8 @@ static IDirectInput8WVtbl ddi8wvt = {
typedef struct
{
/* IUnknown fields */
- IClassFactoryVtbl *lpVtbl;
- DWORD ref;
+ const IClassFactoryVtbl *lpVtbl;
+ LONG ref;
} IClassFactoryImpl;
static HRESULT WINAPI DICF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
@@ -666,7 +666,7 @@ static HRESULT WINAPI DICF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
return S_OK;
}
-static IClassFactoryVtbl DICF_Vtbl = {
+static const IClassFactoryVtbl DICF_Vtbl = {
DICF_QueryInterface,
DICF_AddRef,
DICF_Release,
@@ -678,7 +678,7 @@ static IClassFactoryImpl DINPUT_CF = {&DICF_Vtbl, 1 };
/***********************************************************************
* DllCanUnloadNow (DINPUT.@)
*/
-HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
+HRESULT WINAPI DllCanUnloadNow(void)
{
FIXME("(void): stub\n");
@@ -688,8 +688,7 @@ HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
/***********************************************************************
* DllGetClassObject (DINPUT.@)
*/
-HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,
- LPVOID *ppv)
+HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
diff --git a/reactos/lib/dinput/dinput_private.h b/reactos/lib/dinput/dinput_private.h
index 6beb2f848ef..51385815e48 100644
--- a/reactos/lib/dinput/dinput_private.h
+++ b/reactos/lib/dinput/dinput_private.h
@@ -29,8 +29,8 @@
typedef struct IDirectInputImpl IDirectInputImpl;
struct IDirectInputImpl
{
- LPVOID lpVtbl;
- DWORD ref;
+ const void *lpVtbl;
+ LONG ref;
/* Used to have an unique sequence number for all the events */
DWORD evsequence;
diff --git a/reactos/lib/dinput/effect_linuxinput.c b/reactos/lib/dinput/effect_linuxinput.c
new file mode 100644
index 00000000000..d86b0aca4bf
--- /dev/null
+++ b/reactos/lib/dinput/effect_linuxinput.c
@@ -0,0 +1,927 @@
+/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+
+#include
+#include
+#ifdef HAVE_LINUX_INPUT_H
+# include
+#endif
+#include
+#ifdef HAVE_UNISTD_H
+# include
+#endif
+#include
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "dinput.h"
+
+#include "device_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+static const IDirectInputEffectVtbl LinuxInputEffectVtbl;
+typedef struct LinuxInputEffectImpl LinuxInputEffectImpl;
+struct LinuxInputEffectImpl
+{
+ const void *lpVtbl;
+ LONG ref;
+ GUID guid;
+
+ /* Effect data */
+ struct ff_effect effect;
+
+ /* Parent device */
+ int* fd;
+};
+
+
+/******************************************************************************
+ * DirectInputEffect Functional Helper
+ */
+
+static 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;
+ }
+}
+
+
+/******************************************************************************
+ * DirectInputEffect debug helpers
+ */
+
+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 < (sizeof(flags) / sizeof(flags[0])); i++)
+ if (flags[i].mask & dwFlags)
+ DPRINTF("%s ", flags[i].name);
+ DPRINTF("\n");
+ }
+}
+
+static void _dump_DIENVELOPE(LPDIENVELOPE env)
+{
+ if (env->dwSize != sizeof(DIENVELOPE)) {
+ WARN("Non-standard DIENVELOPE structure size (%ld instead of %d).\n",
+ env->dwSize, sizeof(DIENVELOPE));
+ }
+ TRACE("Envelope has attack (level: %ld time: %ld), fade (level: %ld time: %ld)\n",
+ env->dwAttackLevel, env->dwAttackTime, env->dwFadeLevel, env->dwFadeTime);
+}
+
+static void _dump_DICONSTANTFORCE(LPDICONSTANTFORCE frc)
+{
+ TRACE("Constant force has magnitude %ld\n", frc->lMagnitude);
+}
+
+static void _dump_DIPERIODIC(LPDIPERIODIC frc)
+{
+ TRACE("Periodic force has magnitude %ld, offset %ld, phase %ld, period %ld\n",
+ frc->dwMagnitude, frc->lOffset, frc->dwPhase, frc->dwPeriod);
+}
+
+static void _dump_DIRAMPFORCE(LPDIRAMPFORCE frc)
+{
+ TRACE("Ramp force has start %ld, end %ld\n",
+ frc->lStart, frc->lEnd);
+}
+
+static void _dump_DICONDITION(LPDICONDITION frc)
+{
+ TRACE("Condition has offset %ld, pos/neg coefficients %ld and %ld, pos/neg saturations %ld and %ld, deadband %ld\n",
+ frc->lOffset, frc->lPositiveCoefficient, frc->lNegativeCoefficient,
+ frc->dwPositiveSaturation, frc->dwNegativeSaturation, frc->lDeadBand);
+}
+
+static void _dump_DICUSTOMFORCE(LPDICUSTOMFORCE frc)
+{
+ unsigned int i;
+ TRACE("Custom force uses %ld channels, sample period %ld. Has %ld 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)) {
+ DPRINTF("Custom force data (time aligned, axes in order):\n");
+ for (i = 1; i <= frc->cSamples; ++i) {
+ DPRINTF("%ld ", frc->rglForceData[i]);
+ if (i % frc->cChannels == 0)
+ DPRINTF("\n");
+ }
+ }
+}
+
+static void _dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid)
+{
+ unsigned int i;
+ DWORD type = _typeFromGUID(guid);
+
+ TRACE("Dumping DIEFFECT structure:\n");
+ TRACE(" - dwSize: %ld\n", eff->dwSize);
+ if ((eff->dwSize != sizeof(DIEFFECT)) && (eff->dwSize != sizeof(DIEFFECT_DX5))) {
+ WARN("Non-standard DIEFFECT structure size (%ld instead of %d or %d).\n",
+ eff->dwSize, sizeof(DIEFFECT), sizeof(DIEFFECT_DX5));
+ }
+ TRACE(" - dwFlags: %ld\n", eff->dwFlags);
+ TRACE(" ");
+ _dump_DIEFFECT_flags(eff->dwFlags);
+ TRACE(" - dwDuration: %ld\n", eff->dwDuration);
+ TRACE(" - dwGain: %ld\n", eff->dwGain);
+ if ((eff->dwGain > 10000) || (eff->dwGain < 0))
+ WARN("dwGain is out of range (0 - 10,000)\n");
+ TRACE(" - dwTriggerButton: %ld\n", eff->dwTriggerButton);
+ TRACE(" - dwTriggerRepeatInterval: %ld\n", eff->dwTriggerRepeatInterval);
+ TRACE(" - cAxes: %ld\n", eff->cAxes);
+ TRACE(" - rgdwAxes: %p\n", eff->rgdwAxes);
+ if (TRACE_ON(dinput)) {
+ TRACE(" ");
+ for (i = 0; i < eff->cAxes; ++i)
+ DPRINTF("%ld ", eff->rgdwAxes[i]);
+ DPRINTF("\n");
+ }
+ TRACE(" - rglDirection: %p\n", eff->rglDirection);
+ TRACE(" - lpEnvelope: %p\n", eff->lpEnvelope);
+ TRACE(" - cbTypeSpecificParams: %ld\n", eff->cbTypeSpecificParams);
+ TRACE(" - lpvTypeSpecificParams: %p\n", eff->lpvTypeSpecificParams);
+ if (eff->dwSize > sizeof(DIEFFECT_DX5))
+ TRACE(" - dwStartDelay: %ld\n", eff->dwStartDelay);
+ if (eff->lpEnvelope != NULL)
+ _dump_DIENVELOPE(eff->lpEnvelope);
+ 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 {
+ _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 {
+ _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 {
+ _dump_DIRAMPFORCE(eff->lpvTypeSpecificParams);
+ }
+ } else if (type == DIEFT_CONDITION) {
+ if (eff->cbTypeSpecificParams != sizeof(DICONDITION)) {
+ WARN("Effect claims to be a condition but the type-specific params are the wrong size!\n");
+ } else {
+ _dump_DICONDITION(eff->lpvTypeSpecificParams);
+ }
+ } 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 {
+ _dump_DICUSTOMFORCE(eff->lpvTypeSpecificParams);
+ }
+ }
+}
+
+
+/******************************************************************************
+ * LinuxInputEffectImpl
+ */
+
+static ULONG WINAPI LinuxInputEffectImpl_AddRef(
+ LPDIRECTINPUTEFFECT iface)
+{
+ LinuxInputEffectImpl *This = (LinuxInputEffectImpl *)iface;
+ return InterlockedIncrement(&(This->ref));
+}
+
+static HRESULT WINAPI LinuxInputEffectImpl_Download(
+ LPDIRECTINPUTEFFECT iface)
+{
+ LinuxInputEffectImpl *This = (LinuxInputEffectImpl *)iface;
+
+ TRACE("(this=%p)\n", This);
+
+ if (ioctl(*(This->fd), EVIOCSFF, &This->effect) == -1) {
+ if (errno == ENOMEM) {
+ return DIERR_DEVICEFULL;
+ } else {
+ FIXME("Could not upload effect. Assuming a disconnected device.\n");
+ return DIERR_INPUTLOST;
+ }
+ }
+
+ return DI_OK;
+}
+
+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 = (LinuxInputEffectImpl*)iface;
+
+ TRACE("(this=%p,%p)\n", This, pguid);
+
+ pguid = &This->guid;
+
+ return DI_OK;
+}
+
+static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus(
+ LPDIRECTINPUTEFFECT iface,
+ LPDWORD pdwFlags)
+{
+ TRACE("(this=%p,%p)\n", iface, pdwFlags);
+
+ /* 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 = (LinuxInputEffectImpl *)iface;
+ TRACE("(this=%p,%p,%ld)\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) {
+ peff->rglDirection[0] = (long)(sin(M_PI * 3 * This->effect.direction / 0x7FFF) * 1000);
+ peff->rglDirection[1] = (long)(cos(M_PI * 3 * This->effect.direction / 0x7FFF) * 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) {
+ 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) {
+ /* the linux input ff driver apparently has no support
+ * for setting the device's gain. */
+ peff->dwGain = DI_FFNOMINALMAX;
+ }
+
+ 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->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) {
+ int 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 = (LPDIPERIODIC)(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 = (LPDICONSTANTFORCE)(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 = (LPDICONDITION)(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 = (LPDIRAMPFORCE)(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,%ld,%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 = (LinuxInputEffectImpl*)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 = (LinuxInputEffectImpl*)iface;
+
+ TRACE("(this=%p,%ld,%ld)\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 = dwIterations;
+ 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 = (LinuxInputEffectImpl*)iface;
+ DWORD type = _typeFromGUID(&This->guid);
+ HRESULT retval = DI_OK;
+
+ TRACE("(this=%p,%p,%ld)\n", This, peff, dwFlags);
+
+ _dump_DIEFFECT(peff, &This->guid);
+
+ if ((dwFlags & !DIEP_NORESTART & !DIEP_NODOWNLOAD & !DIEP_START) == 0) {
+ /* set everything */
+ dwFlags = DIEP_AXES | DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE |
+ DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON |
+ DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
+ }
+
+ if (dwFlags & DIEP_AXES) {
+ /* 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;
+ }
+
+ /* 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->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;
+ }
+ } else { /* two axes */
+ if (peff->dwFlags & DIEFF_CARTESIAN) {
+ /* avoid divide-by-zero */
+ if (peff->rglDirection[1] == 0) {
+ if (peff->rglDirection[0] >= 0)
+ This->effect.direction = 0x4000;
+ else if (peff->rglDirection[0] < 0)
+ This->effect.direction = 0xC000;
+ } else {
+ This->effect.direction = (int)(atan(peff->rglDirection[0] / peff->rglDirection[1]) * 0x7FFF / (3 * 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 = (int)(((double)peff->rglDirection[0] - 90) / 35999) * 0x7FFF;
+ }
+ }
+ }
+
+ if (dwFlags & DIEP_DURATION)
+ This->effect.replay.length = peff->dwDuration / 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 (peff->lpEnvelope == NULL) {
+ /* if this type had an envelope, reset it
+ * note that length can never be zero, so we set it to something miniscule */
+ if (env) {
+ env->attack_length = 0x10;
+ env->attack_level = 0x7FFF;
+ env->fade_length = 0x10;
+ env->fade_level = 0x7FFF;
+ }
+ } else {
+ /* did we get passed an envelope for a type that doesn't even have one? */
+ if (!env) return DIERR_INVALIDPARAM;
+ /* copy the envelope */
+ 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;
+ }
+ }
+
+ /* Gain and Sample Period settings are not supported by the linux
+ * event system */
+ if (dwFlags & DIEP_GAIN)
+ TRACE("Gain requested but no gain functionality present.\n");
+
+ if (dwFlags & DIEP_SAMPLEPERIOD)
+ TRACE("Sample period requested but no sample period functionality present.\n");
+
+ if (dwFlags & DIEP_STARTDELAY)
+ 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_INCOMPLETEEFFECT;
+ if (type == DIEFT_PERIODIC) {
+ LPCDIPERIODIC tsp;
+ if (peff->cbTypeSpecificParams != sizeof(DIPERIODIC))
+ return DIERR_INVALIDPARAM;
+ tsp = (LPCDIPERIODIC)(peff->lpvTypeSpecificParams);
+ This->effect.u.periodic.magnitude = (tsp->dwMagnitude / 10) * 32;
+ This->effect.u.periodic.offset = (tsp->lOffset / 10) * 32;
+ This->effect.u.periodic.phase = (tsp->dwPhase / 9) * 8; /* == (/ 36 * 32) */
+ This->effect.u.periodic.period = tsp->dwPeriod / 1000;
+ } else if (type == DIEFT_CONSTANTFORCE) {
+ LPCDICONSTANTFORCE tsp;
+ if (peff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE))
+ return DIERR_INVALIDPARAM;
+ tsp = (LPCDICONSTANTFORCE)(peff->lpvTypeSpecificParams);
+ This->effect.u.constant.level = (tsp->lMagnitude / 10) * 32;
+ } else if (type == DIEFT_RAMPFORCE) {
+ LPCDIRAMPFORCE tsp;
+ if (peff->cbTypeSpecificParams != sizeof(DIRAMPFORCE))
+ return DIERR_INVALIDPARAM;
+ tsp = (LPCDIRAMPFORCE)(peff->lpvTypeSpecificParams);
+ This->effect.u.ramp.start_level = (tsp->lStart / 10) * 32;
+ This->effect.u.ramp.end_level = (tsp->lStart / 10) * 32;
+ } else if (type == DIEFT_CONDITION) {
+ LPCDICONDITION tsp = (LPCDICONDITION)(peff->lpvTypeSpecificParams);
+ if (peff->cbTypeSpecificParams == sizeof(DICONDITION)) {
+ /* One condition block. This needs to be rotated to direction,
+ * and expanded to separate x and y conditions. */
+ int i;
+ double factor[2];
+ factor[0] = asin((This->effect.direction * 3.0 * M_PI) / 0x7FFF);
+ factor[1] = acos((This->effect.direction * 3.0 * M_PI) / 0x7FFF);
+ for (i = 0; i < 2; ++i) {
+ This->effect.u.condition[i].center = (int)(factor[i] * (tsp->lOffset / 10) * 32);
+ This->effect.u.condition[i].right_coeff = (int)(factor[i] * (tsp->lPositiveCoefficient / 10) * 32);
+ This->effect.u.condition[i].left_coeff = (int)(factor[i] * (tsp->lNegativeCoefficient / 10) * 32);
+ This->effect.u.condition[i].right_saturation = (int)(factor[i] * (tsp->dwPositiveSaturation / 10) * 32);
+ This->effect.u.condition[i].left_saturation = (int)(factor[i] * (tsp->dwNegativeSaturation / 10) * 32);
+ This->effect.u.condition[i].deadband = (int)(factor[i] * (tsp->lDeadBand / 10) * 32);
+ }
+ } else if (peff->cbTypeSpecificParams == 2 * sizeof(DICONDITION)) {
+ /* Two condition blocks. Direct parameter copy. */
+ int i;
+ for (i = 0; i < 2; ++i) {
+ This->effect.u.condition[i].center = (tsp[i].lOffset / 10) * 32;
+ This->effect.u.condition[i].right_coeff = (tsp[i].lPositiveCoefficient / 10) * 32;
+ This->effect.u.condition[i].left_coeff = (tsp[i].lNegativeCoefficient / 10) * 32;
+ This->effect.u.condition[i].right_saturation = (tsp[i].dwPositiveSaturation / 10) * 32;
+ This->effect.u.condition[i].left_saturation = (tsp[i].dwNegativeSaturation / 10) * 32;
+ This->effect.u.condition[i].deadband = (tsp[i].lDeadBand / 10) * 32;
+ }
+ } else {
+ return DIERR_INVALIDPARAM;
+ }
+ } 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 ULONG WINAPI LinuxInputEffectImpl_Release(
+ LPDIRECTINPUTEFFECT iface)
+{
+ LinuxInputEffectImpl *This = (LinuxInputEffectImpl *)iface;
+ ULONG ref = InterlockedDecrement(&(This->ref));
+
+ if (ref == 0)
+ HeapFree(GetProcessHeap(), 0, This);
+ return ref;
+}
+
+static HRESULT WINAPI LinuxInputEffectImpl_Stop(
+ LPDIRECTINPUTEFFECT iface)
+{
+ struct input_event event;
+ LinuxInputEffectImpl *This = (LinuxInputEffectImpl *)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 = (LinuxInputEffectImpl *)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;
+}
+
+/******************************************************************************
+ * LinuxInputEffect
+ */
+
+HRESULT linuxinput_create_effect(
+ int* fd,
+ REFGUID rguid,
+ LPDIRECTINPUTEFFECT* peff)
+{
+ LinuxInputEffectImpl* newEffect = HeapAlloc(GetProcessHeap(),
+ HEAP_ZERO_MEMORY, sizeof(LinuxInputEffectImpl));
+ DWORD type = _typeFromGUID(rguid);
+
+ newEffect->lpVtbl = &LinuxInputEffectVtbl;
+ newEffect->ref = 1;
+ memcpy(&(newEffect->guid), rguid, sizeof(*rguid));
+ newEffect->fd = fd;
+
+ /* 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("Unkown force type.\n");
+ HeapFree(GetProcessHeap(), 0, newEffect);
+ return DIERR_INVALIDPARAM;
+ }
+
+ /* mark as non-uploaded */
+ newEffect->effect.id = -1;
+
+ *peff = (LPDIRECTINPUTEFFECT)newEffect;
+
+ TRACE("Creating linux input system effect (%p) with guid %s\n",
+ *peff, _dump_dinput_GUID(rguid));
+
+ return DI_OK;
+}
+
+HRESULT linuxinput_get_info_A(
+ int fd,
+ REFGUID rguid,
+ LPDIEFFECTINFOA info)
+{
+ DWORD type = _typeFromGUID(rguid);
+
+ TRACE("(%d, %s, %p) type=%ld\n", fd, _dump_dinput_GUID(rguid), info, type);
+
+ if (!info) return E_POINTER;
+
+ if (info->dwSize != sizeof(DIEFFECTINFOA)) 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) */
+ strcpy((char*)&(info->tszName), _dump_dinput_GUID(rguid));
+
+ return DI_OK;
+}
+
+HRESULT linuxinput_get_info_W(
+ int fd,
+ REFGUID rguid,
+ LPDIEFFECTINFOW info)
+{
+ DWORD type = _typeFromGUID(rguid);
+
+ TRACE("(%d, %s, %p) type=%ld\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,
+ (WCHAR*)&(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/reactos/lib/dinput/joystick_linux.c b/reactos/lib/dinput/joystick_linux.c
index 14ad4b0e254..6c494277861 100644
--- a/reactos/lib/dinput/joystick_linux.c
+++ b/reactos/lib/dinput/joystick_linux.c
@@ -84,12 +84,12 @@ typedef struct {
} POV;
typedef struct JoystickImpl JoystickImpl;
-static IDirectInputDevice8AVtbl JoystickAvt;
-static IDirectInputDevice8WVtbl JoystickWvt;
+static const IDirectInputDevice8AVtbl JoystickAvt;
+static const IDirectInputDevice8WVtbl JoystickWvt;
struct JoystickImpl
{
- LPVOID lpVtbl;
- DWORD ref;
+ const void *lpVtbl;
+ LONG ref;
GUID guid;
char dev[32];
@@ -254,10 +254,10 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN
inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
char *buffer, DWORD size )
{
- if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size ))
+ if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size ))
return 0;
- if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, buffer, &size ))
+ if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size ))
return 0;
return ERROR_FILE_NOT_FOUND;
@@ -269,28 +269,27 @@ inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
static HRESULT setup_dinput_options(JoystickImpl * device)
{
- char buffer[MAX_PATH+1];
+ char buffer[MAX_PATH+16];
HKEY hkey, appkey = 0;
DWORD len;
buffer[MAX_PATH]='\0';
- if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\dinput", &hkey)) hkey = 0;
+ /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */
+ if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", &hkey)) hkey = 0;
len = GetModuleFileNameA( 0, buffer, MAX_PATH );
if (len && len < MAX_PATH) {
HKEY tmpkey;
-
- if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\AppDefaults", &tmpkey )) {
- char appname[MAX_PATH+16];
- char *p = strrchr( buffer, '\\' );
- if (p!=NULL) {
- strcpy(appname,p+1);
- strcat(appname,"\\dinput");
- TRACE("appname = [%s] \n",appname);
- if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
- }
- RegCloseKey( tmpkey );
+ /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */
+ if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
+ {
+ char *p, *appname = buffer;
+ if ((p = strrchr( appname, '/' ))) appname = p + 1;
+ if ((p = strrchr( appname, '\\' ))) appname = p + 1;
+ strcat( appname, "\\DirectInput" );
+ if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+ RegCloseKey( tmpkey );
}
}
@@ -386,7 +385,7 @@ static HRESULT setup_dinput_options(JoystickImpl * device)
return DI_OK;
}
-void calculate_ids(JoystickImpl* device)
+static void calculate_ids(JoystickImpl* device)
{
int i;
int axis = 0;
@@ -437,7 +436,7 @@ void calculate_ids(JoystickImpl* device)
}
}
-static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, LPDIRECTINPUTDEVICEA* pdev)
+static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *dinput, LPDIRECTINPUTDEVICEA* pdev)
{
DWORD i;
JoystickImpl* newDevice;
@@ -553,7 +552,7 @@ static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput,
IDirectInputDevice_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
InitializeCriticalSection(&(newDevice->crit));
- newDevice->crit.DebugInfo->Spare[1] = (DWORD)"DINPUT_Mouse";
+ newDevice->crit.DebugInfo->Spare[0] = (DWORD_PTR)"DINPUT_Mouse";
newDevice->devcaps.dwSize = sizeof(newDevice->devcaps);
newDevice->devcaps.dwFlags = DIDC_ATTACHED;
@@ -689,7 +688,7 @@ static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
/* release the data transform filter */
release_DataFormat(This->transform);
- This->crit.DebugInfo->Spare[1] = 0;
+ This->crit.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&(This->crit));
IDirectInputDevice_Release((LPDIRECTINPUTDEVICE8A)This->dinput);
@@ -831,7 +830,7 @@ static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
return DI_NOEFFECT;
}
-LONG map_axis(JoystickImpl * This, short val, short index)
+static LONG map_axis(JoystickImpl * This, short val, short index)
{
double fval = val;
double fmin = This->props[index].lMin;
@@ -849,7 +848,7 @@ LONG map_axis(JoystickImpl * This, short val, short index)
}
/* convert wine format offset to user format object index */
-int offset_to_object(JoystickImpl *This, int offset)
+static int offset_to_object(JoystickImpl *This, int offset)
{
int i;
@@ -1094,7 +1093,7 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceData(
return hr;
}
-int find_property(JoystickImpl * This, LPCDIPROPHEADER ph)
+static int find_property(JoystickImpl * This, LPCDIPROPHEADER ph)
{
int i;
if (ph->dwHow == DIPH_BYOFFSET) {
@@ -1132,7 +1131,7 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(
_dump_DIPROPHEADER(ph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
TRACE("buffersize = %ld\n",pd->dwData);
@@ -1197,7 +1196,7 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(
break;
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -1213,7 +1212,7 @@ static HRESULT WINAPI JoystickAImpl_SetEventNotification(
) {
JoystickImpl *This = (JoystickImpl *)iface;
- TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+ TRACE("(this=%p,%p)\n",This,hnd);
This->hEvent = hnd;
return DI_OK;
}
@@ -1428,7 +1427,7 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(
_dump_DIPROPHEADER(pdiph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
TRACE(" return buffersize = %d\n",This->queue_len);
@@ -1469,7 +1468,7 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(
break;
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -1640,7 +1639,7 @@ HRESULT WINAPI JoystickWImpl_GetDeviceInfo(
return DI_OK;
}
-static IDirectInputDevice8AVtbl JoystickAvt =
+static const IDirectInputDevice8AVtbl JoystickAvt =
{
IDirectInputDevice2AImpl_QueryInterface,
IDirectInputDevice2AImpl_AddRef,
@@ -1682,7 +1681,7 @@ static IDirectInputDevice8AVtbl JoystickAvt =
# define XCAST(fun) (void*)
#endif
-static IDirectInputDevice8WVtbl SysJoystickWvt =
+static const IDirectInputDevice8WVtbl SysJoystickWvt =
{
IDirectInputDevice2WImpl_QueryInterface,
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
diff --git a/reactos/lib/dinput/joystick_linuxinput.c b/reactos/lib/dinput/joystick_linuxinput.c
index 3b17f51371f..4660ca440d0 100644
--- a/reactos/lib/dinput/joystick_linuxinput.c
+++ b/reactos/lib/dinput/joystick_linuxinput.c
@@ -3,6 +3,7 @@
* 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
@@ -43,6 +44,9 @@
#endif
#ifdef HAVE_LINUX_INPUT_H
# include
+# if defined(EVIOCGBIT) && defined(EV_ABS) && defined(BTN_PINKIE)
+# define HAVE_CORRECT_LINUXINPUT_H
+# endif
#endif
#include "wine/debug.h"
@@ -65,13 +69,25 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
#define WINE_JOYSTICK_AXIS_BASE 0
#define WINE_JOYSTICK_BUTTON_BASE 8
+typedef struct EffectListItem EffectListItem;
+struct EffectListItem
+{
+ LPDIRECTINPUTEFFECT ref;
+ struct EffectListItem* next;
+};
+
+/* implemented in effect_linuxinput.c */
+HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, LPDIRECTINPUTEFFECT* peff);
+HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
+HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
+
typedef struct JoystickImpl JoystickImpl;
-static IDirectInputDevice8AVtbl JoystickAvt;
-static IDirectInputDevice8WVtbl JoystickWvt;
+static const IDirectInputDevice8AVtbl JoystickAvt;
+static const IDirectInputDevice8WVtbl JoystickWvt;
struct JoystickImpl
{
- LPVOID lpVtbl;
- DWORD ref;
+ const void *lpVtbl;
+ LONG ref;
GUID guid;
@@ -97,6 +113,12 @@ struct JoystickImpl
BOOL overflow;
DIJOYSTATE2 js;
+ /* Force feedback variables */
+ BOOL has_ff;
+ int num_effects;
+ EffectListItem* top_effect;
+ int ff_state;
+
/* data returned by the EVIOCGABS() ioctl */
int axes[ABS_MAX+1][5];
@@ -107,9 +129,11 @@ struct JoystickImpl
#define AXE_ABSFLAT 4
- /* data returned by EVIOCGBIT for EV_ABS and EV_KEY */
+ /* 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];
};
/* This GUID is slightly different from the linux joystick one. Take note. */
@@ -124,17 +148,24 @@ static void fake_current_js_state(JoystickImpl *ji);
#define test_bit(arr,bit) (((BYTE*)arr)[bit>>3]&(1<<(bit&7)))
-static int joydev_have(void)
+static int joydev_have(BOOL require_ff)
{
- int i, fd;
+ int i, fd, flags, num_effects;
int havejoy = 0;
for (i=0;i<64;i++) {
char buf[200];
BYTE absbits[(ABS_MAX+7)/8],keybits[(KEY_MAX+7)/8];
+ BYTE evbits[(EV_MAX+7)/8],ffbits[(FF_MAX+7)/8];
sprintf(buf,EVDEVPREFIX"%d",i);
- if (-1!=(fd=open(buf,O_RDONLY))) {
+
+ if (require_ff)
+ flags = O_RDWR;
+ else
+ flags = O_RDONLY;
+
+ if (-1!=(fd=open(buf,flags))) {
if (-1==ioctl(fd,EVIOCGBIT(EV_ABS,sizeof(absbits)),absbits)) {
perror("EVIOCGBIT EV_ABS");
close(fd);
@@ -145,6 +176,23 @@ static int joydev_have(void)
close(fd);
continue;
}
+
+ /* test for force feedback if it's required */
+ if (require_ff) {
+ if ((-1==ioctl(fd,EVIOCGBIT(0,sizeof(evbits)),evbits))) {
+ perror("EVIOCGBIT 0");
+ close(fd);
+ continue;
+ }
+ if ( (!test_bit(evbits,EV_FF))
+ || (-1==ioctl(fd,EVIOCGBIT(EV_FF,sizeof(ffbits)),ffbits))
+ || (-1==ioctl(fd,EVIOCGEFFECTS,&num_effects))
+ || (num_effects <= 0)) {
+ 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(absbits,ABS_X) && test_bit(absbits,ABS_Y) &&
@@ -176,10 +224,12 @@ static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
return FALSE;
+#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
if (dwFlags & DIEDFL_FORCEFEEDBACK)
return FALSE;
+#endif
- havejoy = joydev_have();
+ havejoy = joydev_have(dwFlags & DIEDFL_FORCEFEEDBACK);
if (!havejoy)
return FALSE;
@@ -214,10 +264,12 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
return FALSE;
+#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
if (dwFlags & DIEDFL_FORCEFEEDBACK)
return FALSE;
+#endif
- havejoy = joydev_have();
+ havejoy = joydev_have(dwFlags & DIEDFL_FORCEFEEDBACK);
if (!havejoy)
return FALSE;
@@ -240,7 +292,7 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN
return TRUE;
}
-static JoystickImpl *alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput)
+static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *dinput)
{
JoystickImpl* newDevice;
int i;
@@ -250,6 +302,9 @@ static JoystickImpl *alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *d
newDevice->ref = 1;
newDevice->joyfd = -1;
newDevice->dinput = dinput;
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ newDevice->ff_state = FF_STATUS_STOPPED;
+#endif
memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
for (i=0;iwantmin[i] = -32768;
@@ -269,7 +324,7 @@ static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, RE
{
int havejoy = 0;
- havejoy = joydev_have();
+ havejoy = joydev_have(FALSE);
if (!havejoy)
return DIERR_DEVICENOTREG;
@@ -296,7 +351,7 @@ static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, RE
{
int havejoy = 0;
- havejoy = joydev_have();
+ havejoy = joydev_have(FALSE);
if (!havejoy)
return DIERR_DEVICENOTREG;
@@ -338,6 +393,9 @@ static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
if (ref)
return ref;
+ /* Reset the FF state, free all effects, etc */
+ IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET);
+
/* Free the data queue */
HeapFree(GetProcessHeap(),0,This->data_queue);
@@ -379,19 +437,32 @@ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
int i;
JoystickImpl *This = (JoystickImpl *)iface;
char buf[200];
+ BOOL readonly = TRUE;
TRACE("(this=%p)\n",This);
if (This->joyfd!=-1)
return 0;
for (i=0;i<64;i++) {
sprintf(buf,EVDEVPREFIX"%d",i);
- if (-1==(This->joyfd=open(buf,O_RDONLY))) {
- if (errno==ENODEV)
- return DIERR_NOTFOUND;
- perror(buf);
- continue;
+ if (-1==(This->joyfd=open(buf,O_RDWR))) {
+ if (-1==(This->joyfd=open(buf,O_RDONLY))) {
+ /* Couldn't open the device at all */
+ if (errno==ENODEV)
+ return DIERR_NOTFOUND;
+ perror(buf);
+ continue;
+ }
+ 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",buf);
+ }
}
- if ((-1!=ioctl(This->joyfd,EVIOCGBIT(EV_ABS,sizeof(This->absbits)),This->absbits)) &&
+ else {
+ /* Opened device in read-write */
+ readonly = FALSE;
+ }
+ if ((-1!=ioctl(This->joyfd,EVIOCGBIT(0,sizeof(This->evbits)),This->evbits)) &&
+ (-1!=ioctl(This->joyfd,EVIOCGBIT(EV_ABS,sizeof(This->absbits)),This->absbits)) &&
(-1!=ioctl(This->joyfd,EVIOCGBIT(EV_KEY,sizeof(This->keybits)),This->keybits)) &&
(test_bit(This->absbits,ABS_X) && test_bit(This->absbits,ABS_Y) &&
(test_bit(This->keybits,BTN_TRIGGER)||
@@ -407,6 +478,30 @@ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
if (This->joyfd==-1)
return DIERR_NOTFOUND;
+ This->has_ff = FALSE;
+ This->num_effects = 0;
+
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ if (!readonly && test_bit(This->evbits, EV_FF)) {
+ if (-1!=ioctl(This->joyfd,EVIOCGBIT(EV_FF,sizeof(This->ffbits)),This->ffbits)) {
+ if (-1!=ioctl(This->joyfd,EVIOCGEFFECTS,&This->num_effects)
+ && This->num_effects > 0) {
+ This->has_ff = TRUE;
+ TRACE("Joystick seems to be capable of force feedback.\n");
+ }
+ else {
+ TRACE("Joystick does not support any effects, disabling force feedback.\n");
+ }
+ }
+ else {
+ TRACE("Could not get EV_FF bits; disabling force feedback.\n");
+ }
+ }
+ else {
+ TRACE("Force feedback disabled (device is readonly or joystick incapable).\n");
+ }
+#endif
+
for (i=0;iabsbits,i)) {
if (-1==ioctl(This->joyfd,EVIOCGABS(i),&(This->axes[i])))
@@ -468,7 +563,9 @@ map_axis(JoystickImpl* This, int axis, int val) {
if (xmin == xmax) return val;
/* map the value from the hmin-hmax range into the wmin-wmax range */
- ret = (val * (wmax-wmin)) / (hmax-hmin) + wmin;
+ ret = ((val-hmin) * (wmax-wmin)) / (hmax-hmin) + wmin;
+
+ TRACE("xmin=%d xmax=%d hmin=%d hmax=%d wmin=%d wmax=%d val=%d ret=%d\n", xmin, xmax, hmin, hmax, wmin, wmax, val, ret);
#if 0
/* deadzone doesn't work comfortably enough right now. needs more testing*/
@@ -492,6 +589,8 @@ static void fake_current_js_state(JoystickImpl *ji)
ji->js.lRx = map_axis(ji, ABS_RX, ji->axes[ABS_RX][AXE_ABS]);
ji->js.lRy = map_axis(ji, ABS_RY, ji->axes[ABS_RY][AXE_ABS]);
ji->js.lRz = map_axis(ji, ABS_RZ, ji->axes[ABS_RZ][AXE_ABS]);
+ ji->js.rglSlider[0] = map_axis(ji, ABS_THROTTLE, ji->axes[ABS_THROTTLE][AXE_ABS]);
+ ji->js.rglSlider[1] = map_axis(ji, ABS_RUDDER, ji->axes[ABS_RUDDER ][AXE_ABS]);
}
static void joy_polldev(JoystickImpl *This) {
@@ -613,11 +712,24 @@ static void joy_polldev(JoystickImpl *This) {
This->js.lRz = map_axis(This,ABS_RZ,ie.value);
GEN_EVENT(DIJOFS_RZ,This->js.lRz,ie.time.tv_usec,(This->dinput->evsequence)++);
break;
+ case ABS_THROTTLE:
+ This->js.rglSlider[0] = map_axis(This,ABS_THROTTLE,ie.value);
+ GEN_EVENT(DIJOFS_SLIDER(0),This->js.rglSlider[0],ie.time.tv_usec,(This->dinput->evsequence)++);
+ break;
+ case ABS_RUDDER:
+ This->js.rglSlider[1] = map_axis(This,ABS_RUDDER,ie.value);
+ GEN_EVENT(DIJOFS_SLIDER(1),This->js.rglSlider[1],ie.time.tv_usec,(This->dinput->evsequence)++);
+ break;
default:
FIXME("unhandled joystick axe event (code %d, value %d)\n",ie.code,ie.value);
break;
}
break;
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ case EV_FF_STATUS:
+ This->ff_state = ie.value;
+ break;
+#endif
default:
FIXME("joystick cannot handle type %d event (code %d)\n",ie.type,ie.code);
break;
@@ -683,7 +795,7 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
@@ -701,6 +813,8 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
case 12: /* Rx */
case 16: /* Ry */
case 20: /* Rz */
+ case 24: /* Slider 0 -> Throttle */
+ case 28: /* Slider 1 -> Rudder */
This->wantmin[ph->dwObj/4] = pr->lMin;
This->wantmax[ph->dwObj/4] = pr->lMax;
break;
@@ -717,7 +831,7 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
break;
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -733,7 +847,7 @@ static HRESULT WINAPI JoystickAImpl_SetEventNotification(
) {
JoystickImpl *This = (JoystickImpl *)iface;
- TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+ TRACE("(this=%p,%p)\n",This,hnd);
This->hEvent = hnd;
return DI_OK;
}
@@ -765,6 +879,9 @@ static HRESULT WINAPI JoystickAImpl_GetCapabilities(
buttons=0;
for (i=0;ikeybits,i)) buttons++;
+ if (This->has_ff)
+ lpDIDevCaps->dwFlags |= DIDC_FORCEFEEDBACK;
+
lpDIDevCaps->dwAxes = axes;
lpDIDevCaps->dwButtons = buttons;
@@ -795,7 +912,6 @@ static HRESULT WINAPI JoystickAImpl_EnumObjects(
DIDEVICEOBJECTINSTANCEA ddoi;
int xfd = This->joyfd;
-
TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
if (TRACE_ON(dinput)) {
TRACE(" - flags = ");
@@ -803,7 +919,9 @@ static HRESULT WINAPI JoystickAImpl_EnumObjects(
TRACE("\n");
}
- if (xfd == -1) return DIERR_NOTACQUIRED;
+ /* We need to work even if we're not yet acquired */
+ if (xfd == -1)
+ IDirectInputDevice8_Acquire(iface);
/* Only the fields till dwFFMaxForce are relevant */
ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
@@ -846,14 +964,27 @@ static HRESULT WINAPI JoystickAImpl_EnumObjects(
ddoi.guidType = GUID_Slider;
ddoi.dwOfs = DIJOFS_SLIDER(0);
break;
+ case ABS_RUDDER:
+ ddoi.guidType = GUID_Slider;
+ ddoi.dwOfs = DIJOFS_SLIDER(1);
+ break;
default:
FIXME("unhandled abs axis %d, ignoring!\n",i);
}
ddoi.dwType = DIDFT_MAKEINSTANCE((1<has_ff)
+ ddoi.dwFlags |= DIDOI_FFACTUATOR;
+ }
sprintf(ddoi.tszName, "%d-Axis", i);
_dump_OBJECTINSTANCEA(&ddoi);
- if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE)
- return DI_OK;
+ if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) {
+ /* return to unaquired state if that's where we were */
+ if (xfd == -1)
+ IDirectInputDevice8_Unacquire(iface);
+ return DI_OK;
+ }
}
}
@@ -936,13 +1067,18 @@ static HRESULT WINAPI JoystickAImpl_EnumObjects(
}
sprintf(ddoi.tszName, "%d-Button", i);
_dump_OBJECTINSTANCEA(&ddoi);
- if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE)
- return DI_OK;
+ if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) {
+ /* return to unaquired state if that's where we were */
+ if (xfd == -1)
+ IDirectInputDevice8_Unacquire(iface);
+ return DI_OK;
+ }
}
}
- if (xfd!=This->joyfd)
- close(xfd);
+ /* return to unaquired state if that's where we were */
+ if (xfd == -1)
+ IDirectInputDevice8_Unacquire(iface);
return DI_OK;
}
@@ -978,7 +1114,7 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
_dump_DIPROPHEADER(pdiph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
@@ -999,7 +1135,7 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -1008,7 +1144,351 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
return DI_OK;
}
-static IDirectInputDevice8AVtbl JoystickAvt =
+/******************************************************************************
+ * CreateEffect - Create a new FF effect with the specified params
+ */
+static HRESULT WINAPI JoystickAImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface,
+ REFGUID rguid,
+ LPCDIEFFECT lpeff,
+ LPDIRECTINPUTEFFECT *ppdef,
+ LPUNKNOWN pUnkOuter)
+{
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ EffectListItem* new = NULL;
+ HRESULT retval = DI_OK;
+#endif
+
+ JoystickImpl* This = (JoystickImpl*)iface;
+ TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
+
+#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ TRACE("not available (compiled w/o ff support)\n");
+ *ppdef = NULL;
+ return DI_OK;
+#else
+
+ new = malloc(sizeof(EffectListItem));
+ new->next = This->top_effect;
+ This->top_effect = new;
+
+ retval = linuxinput_create_effect(&(This->joyfd), rguid, &(new->ref));
+ if (retval != DI_OK)
+ return retval;
+
+ if (lpeff != NULL)
+ retval = IDirectInputEffect_SetParameters(new->ref, lpeff, 0);
+ if (retval != DI_OK && retval != DI_DOWNLOADSKIPPED)
+ return retval;
+
+ *ppdef = new->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 JoystickAImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface,
+ LPDIENUMEFFECTSCALLBACKA lpCallback,
+ LPVOID pvRef,
+ DWORD dwEffType)
+{
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ DIEFFECTINFOA dei; /* feif */
+ DWORD type = DIEFT_GETTYPE(dwEffType);
+ JoystickImpl* This = (JoystickImpl*)iface;
+ int xfd = This->joyfd;
+
+ TRACE("(this=%p,%p,%ld) type=%ld fd=%d\n", This, pvRef, dwEffType, type, xfd);
+
+ dei.dwSize = sizeof(DIEFFECTINFOA);
+
+ /* We need to return something even if we're not yet acquired */
+ if (xfd == -1)
+ IDirectInputDevice8_Acquire(iface);
+
+ if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
+ && test_bit(This->ffbits, FF_CONSTANT)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
+ (*lpCallback)(&dei, pvRef);
+ }
+
+ if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
+ && test_bit(This->ffbits, FF_PERIODIC)) {
+ if (test_bit(This->ffbits, FF_SQUARE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SINE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_TRIANGLE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SAW_UP)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SAW_DOWN)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
+ (*lpCallback)(&dei, pvRef);
+ }
+ }
+
+ if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
+ && test_bit(This->ffbits, FF_RAMP)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
+ (*lpCallback)(&dei, pvRef);
+ }
+
+ if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
+ if (test_bit(This->ffbits, FF_SPRING)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_DAMPER)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_INERTIA)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_FRICTION)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
+ (*lpCallback)(&dei, pvRef);
+ }
+ }
+
+ /* return to unaquired state if that's where it was */
+ if (xfd == -1)
+ IDirectInputDevice8_Unacquire(iface);
+#endif
+
+ return DI_OK;
+}
+
+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 = (JoystickImpl*)iface;
+ int xfd = This->joyfd;
+
+ TRACE("(this=%p,%p,%ld) type=%ld fd=%d\n", This, pvRef, dwEffType, type, xfd);
+
+ dei.dwSize = sizeof(DIEFFECTINFOW);
+
+ /* We need to return something even if we're not yet acquired */
+ if (xfd == -1)
+ IDirectInputDevice8_Acquire(iface);
+
+ if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
+ && test_bit(This->ffbits, FF_CONSTANT)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
+ (*lpCallback)(&dei, pvRef);
+ }
+
+ if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
+ && test_bit(This->ffbits, FF_PERIODIC)) {
+ if (test_bit(This->ffbits, FF_SQUARE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SINE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_TRIANGLE)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SAW_UP)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_SAW_DOWN)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
+ (*lpCallback)(&dei, pvRef);
+ }
+ }
+
+ if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
+ && test_bit(This->ffbits, FF_RAMP)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
+ (*lpCallback)(&dei, pvRef);
+ }
+
+ if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
+ if (test_bit(This->ffbits, FF_SPRING)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_DAMPER)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_INERTIA)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
+ (*lpCallback)(&dei, pvRef);
+ }
+ if (test_bit(This->ffbits, FF_FRICTION)) {
+ IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
+ (*lpCallback)(&dei, pvRef);
+ }
+ }
+
+ /* return to unaquired 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 JoystickAImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface,
+ LPDIEFFECTINFOA pdei,
+ REFGUID guid)
+{
+ JoystickImpl* This = (JoystickImpl*)iface;
+
+ TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid));
+
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ return linuxinput_get_info_A(This->joyfd, guid, pdei);
+#else
+ return DI_OK;
+#endif
+}
+
+static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,
+ LPDIEFFECTINFOW pdei,
+ REFGUID guid)
+{
+ JoystickImpl* This = (JoystickImpl*)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 JoystickAImpl_GetForceFeedbackState(
+ LPDIRECTINPUTDEVICE8A iface,
+ LPDWORD pdwOut)
+{
+ JoystickImpl* This = (JoystickImpl*)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 JoystickAImpl_SendForceFeedbackCommand(
+ LPDIRECTINPUTDEVICE8A iface,
+ DWORD dwFlags)
+{
+ JoystickImpl* This = (JoystickImpl*)iface;
+ TRACE("(this=%p,%ld)\n", This, dwFlags);
+
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+ if (dwFlags == DISFFC_STOPALL) {
+ /* Stop all effects */
+ EffectListItem* itr = This->top_effect;
+ while (itr) {
+ IDirectInputEffect_Stop(itr->ref);
+ itr = itr->next;
+ }
+ } else if (dwFlags == DISFFC_RESET) {
+ /* Stop, unload, release and free all effects */
+ /* This returns the device to its "bare" state */
+ while (This->top_effect) {
+ EffectListItem* temp = This->top_effect;
+ IDirectInputEffect_Stop(temp->ref);
+ IDirectInputEffect_Unload(temp->ref);
+ IDirectInputEffect_Release(temp->ref);
+ This->top_effect = temp->next;
+ free(temp);
+ }
+ } else if (dwFlags == DISFFC_PAUSE || dwFlags == DISFFC_CONTINUE) {
+ FIXME("No support for Pause or Continue in linux\n");
+ } else if (dwFlags == DISFFC_SETACTUATORSOFF
+ || dwFlags == DISFFC_SETACTUATORSON) {
+ FIXME("No direct actuator control in linux\n");
+ } else {
+ FIXME("Unknown Force Feedback Command!\n");
+ 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 JoystickAImpl_EnumCreatedEffectObjects(
+ LPDIRECTINPUTDEVICE8A iface,
+ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
+ LPVOID pvRef,
+ DWORD dwFlags)
+{
+ /* this function is safe to call on non-ff-enabled builds */
+
+ JoystickImpl* This = (JoystickImpl*)iface;
+ EffectListItem* itr = This->top_effect;
+ TRACE("(this=%p,%p,%p,%ld)\n", This, lpCallback, pvRef, dwFlags);
+
+ if (!lpCallback)
+ return DIERR_INVALIDPARAM;
+
+ if (dwFlags != 0)
+ FIXME("Flags specified, but no flags exist yet (DX9)!");
+
+ while (itr) {
+ (*lpCallback)(itr->ref, pvRef);
+ itr = itr->next;
+ }
+
+ return DI_OK;
+}
+
+static const IDirectInputDevice8AVtbl JoystickAvt =
{
IDirectInputDevice2AImpl_QueryInterface,
IDirectInputDevice2AImpl_AddRef,
@@ -1028,12 +1508,12 @@ static IDirectInputDevice8AVtbl JoystickAvt =
IDirectInputDevice2AImpl_GetDeviceInfo,
IDirectInputDevice2AImpl_RunControlPanel,
IDirectInputDevice2AImpl_Initialize,
- IDirectInputDevice2AImpl_CreateEffect,
- IDirectInputDevice2AImpl_EnumEffects,
- IDirectInputDevice2AImpl_GetEffectInfo,
- IDirectInputDevice2AImpl_GetForceFeedbackState,
- IDirectInputDevice2AImpl_SendForceFeedbackCommand,
- IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
+ JoystickAImpl_CreateEffect,
+ JoystickAImpl_EnumEffects,
+ JoystickAImpl_GetEffectInfo,
+ JoystickAImpl_GetForceFeedbackState,
+ JoystickAImpl_SendForceFeedbackCommand,
+ JoystickAImpl_EnumCreatedEffectObjects,
IDirectInputDevice2AImpl_Escape,
JoystickAImpl_Poll,
IDirectInputDevice2AImpl_SendDeviceData,
@@ -1050,7 +1530,7 @@ static IDirectInputDevice8AVtbl JoystickAvt =
# define XCAST(fun) (void*)
#endif
-static IDirectInputDevice8WVtbl JoystickWvt =
+static const IDirectInputDevice8WVtbl JoystickWvt =
{
IDirectInputDevice2WImpl_QueryInterface,
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
@@ -1070,12 +1550,12 @@ static IDirectInputDevice8WVtbl JoystickWvt =
IDirectInputDevice2WImpl_GetDeviceInfo,
XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
- XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
- IDirectInputDevice2WImpl_EnumEffects,
- IDirectInputDevice2WImpl_GetEffectInfo,
- XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
- XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
- XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
+ XCAST(CreateEffect)JoystickAImpl_CreateEffect,
+ JoystickWImpl_EnumEffects,
+ JoystickWImpl_GetEffectInfo,
+ XCAST(GetForceFeedbackState)JoystickAImpl_GetForceFeedbackState,
+ XCAST(SendForceFeedbackCommand)JoystickAImpl_SendForceFeedbackCommand,
+ XCAST(EnumCreatedEffectObjects)JoystickAImpl_EnumCreatedEffectObjects,
XCAST(Escape)IDirectInputDevice2AImpl_Escape,
XCAST(Poll)JoystickAImpl_Poll,
XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
diff --git a/reactos/lib/dinput/keyboard.c b/reactos/lib/dinput/keyboard.c
index c8269ab63cb..aa6cbcbe387 100644
--- a/reactos/lib/dinput/keyboard.c
+++ b/reactos/lib/dinput/keyboard.c
@@ -40,14 +40,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256
-static IDirectInputDevice8AVtbl SysKeyboardAvt;
-static IDirectInputDevice8WVtbl SysKeyboardWvt;
+static const IDirectInputDevice8AVtbl SysKeyboardAvt;
+static const IDirectInputDevice8WVtbl SysKeyboardWvt;
typedef struct SysKeyboardImpl SysKeyboardImpl;
struct SysKeyboardImpl
{
- LPVOID lpVtbl;
- DWORD ref;
+ const void *lpVtbl;
+ LONG ref;
GUID guid;
IDirectInputImpl* dinput;
@@ -83,11 +83,11 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &keyboard_crit,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
- 0, 0, { 0, (DWORD)(__FILE__ ": keyboard_crit") }
+ 0, 0, { (DWORD_PTR)(__FILE__ ": keyboard_crit") }
};
static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 };
-static DWORD keyboard_users = 0;
+static LONG keyboard_users = 0;
static HHOOK keyboard_hook = NULL;
LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
@@ -238,7 +238,7 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
return FALSE;
}
-static SysKeyboardImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput)
+static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInputImpl *dinput)
{
SysKeyboardImpl* newDevice;
DWORD kbd_users;
@@ -342,7 +342,7 @@ static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
@@ -356,7 +356,7 @@ static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
break;
}
default:
- WARN("Unknown type %ld\n",(DWORD)rguid);
+ WARN("Unknown type %p\n",rguid);
break;
}
}
@@ -373,7 +373,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetProperty(
TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPDIPROPDWORD pd = (LPDIPROPDWORD)ph;
@@ -387,7 +387,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetProperty(
break;
}
default:
- WARN("Unknown type %ld\n",(DWORD)rguid);
+ WARN("Unknown type %p\n",rguid);
break;
}
}
@@ -597,7 +597,7 @@ static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8
HANDLE hnd) {
SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
- TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+ TRACE("(this=%p,%p)\n",This,hnd);
This->hEvent = hnd;
return DI_OK;
@@ -747,7 +747,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface
return DI_OK;
}
-static IDirectInputDevice8AVtbl SysKeyboardAvt =
+static const IDirectInputDevice8AVtbl SysKeyboardAvt =
{
IDirectInputDevice2AImpl_QueryInterface,
IDirectInputDevice2AImpl_AddRef,
@@ -789,7 +789,7 @@ static IDirectInputDevice8AVtbl SysKeyboardAvt =
# define XCAST(fun) (void*)
#endif
-static IDirectInputDevice8WVtbl SysKeyboardWvt =
+static const IDirectInputDevice8WVtbl SysKeyboardWvt =
{
IDirectInputDevice2WImpl_QueryInterface,
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
diff --git a/reactos/lib/dinput/mouse.c b/reactos/lib/dinput/mouse.c
index eb1c64c571d..f731d12a062 100644
--- a/reactos/lib/dinput/mouse.c
+++ b/reactos/lib/dinput/mouse.c
@@ -95,8 +95,8 @@ static const DIDATAFORMAT Wine_InternalMouseFormat = {
(LPDIOBJECTDATAFORMAT) Wine_InternalMouseObjectFormat
};
-static IDirectInputDevice8AVtbl SysMouseAvt;
-static IDirectInputDevice8WVtbl SysMouseWvt;
+static const IDirectInputDevice8AVtbl SysMouseAvt;
+static const IDirectInputDevice8WVtbl SysMouseWvt;
typedef struct SysMouseImpl SysMouseImpl;
@@ -108,8 +108,8 @@ typedef enum {
struct SysMouseImpl
{
- LPVOID lpVtbl;
- DWORD ref;
+ const void *lpVtbl;
+ LONG ref;
GUID guid;
IDirectInputImpl *dinput;
@@ -241,7 +241,7 @@ static BOOL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINST
return FALSE;
}
-static SysMouseImpl *alloc_device(REFGUID rguid, LPVOID mvt, IDirectInputImpl *dinput)
+static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputImpl *dinput)
{
int offset_array[WINE_INTERNALMOUSE_NUM_OBJS] = {
FIELD_OFFSET(Wine_InternalMouseData, lX),
@@ -363,7 +363,7 @@ static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
{
SysMouseImpl *This = (SysMouseImpl *)iface;
- TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
+ TRACE("(this=%p,%p,0x%08lx)\n",This,hwnd,dwflags);
if (TRACE_ON(dinput)) {
TRACE(" cooperative level : ");
@@ -865,7 +865,7 @@ static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
@@ -884,7 +884,7 @@ static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,
break;
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -908,7 +908,7 @@ static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
_dump_DIPROPHEADER(pdiph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
@@ -943,7 +943,7 @@ static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
}
default:
- FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -960,7 +960,7 @@ static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A i
HANDLE hnd) {
SysMouseImpl *This = (SysMouseImpl *)iface;
- TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
+ TRACE("(this=%p,%p)\n",This,hnd);
This->hEvent = hnd;
@@ -1133,7 +1133,7 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, L
}
-static IDirectInputDevice8AVtbl SysMouseAvt =
+static const IDirectInputDevice8AVtbl SysMouseAvt =
{
IDirectInputDevice2AImpl_QueryInterface,
IDirectInputDevice2AImpl_AddRef,
@@ -1175,7 +1175,7 @@ static IDirectInputDevice8AVtbl SysMouseAvt =
# define XCAST(fun) (void*)
#endif
-static IDirectInputDevice8WVtbl SysMouseWvt =
+static const IDirectInputDevice8WVtbl SysMouseWvt =
{
IDirectInputDevice2WImpl_QueryInterface,
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
diff --git a/reactos/lib/dinput/regsvr.c b/reactos/lib/dinput/regsvr.c
index 6bdd46a0e3c..e005f727396 100644
--- a/reactos/lib/dinput/regsvr.c
+++ b/reactos/lib/dinput/regsvr.c
@@ -530,7 +530,7 @@ static struct regsvr_interface const interface_list[] = {
/***********************************************************************
* DllRegisterServer (DINPUT.@)
*/
-HRESULT WINAPI DINPUT_DllRegisterServer(void)
+HRESULT WINAPI DllRegisterServer(void)
{
HRESULT hr;
@@ -545,7 +545,7 @@ HRESULT WINAPI DINPUT_DllRegisterServer(void)
/***********************************************************************
* DllUnregisterServer (DINPUT.@)
*/
-HRESULT WINAPI DINPUT_DllUnregisterServer(void)
+HRESULT WINAPI DllUnregisterServer(void)
{
HRESULT hr;
diff --git a/reactos/lib/dinput/version.rc b/reactos/lib/dinput/version.rc
index 53df0b62226..65dc50a1512 100644
--- a/reactos/lib/dinput/version.rc
+++ b/reactos/lib/dinput/version.rc
@@ -1,26 +1,26 @@
-/*
- * Copyright 2001 Ove Kaaven
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define WINE_FILEDESCRIPTION_STR "Wine DirectInput"
-#define WINE_FILENAME_STR "dinput.dll"
-#define WINE_FILEVERSION 5,1,2600,881
-#define WINE_FILEVERSION_STR "5.1.2600.881"
-#define WINE_PRODUCTVERSION 5,1,2600,881
-#define WINE_PRODUCTVERSION_STR "5.1"
-
-#include "wine/wine_common_ver.rc"
+/*
+ * Copyright 2001 Ove Kaaven
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine DirectInput"
+#define WINE_FILENAME_STR "dinput.dll"
+#define WINE_FILEVERSION 5,1,2600,881
+#define WINE_FILEVERSION_STR "5.1.2600.881"
+#define WINE_PRODUCTVERSION 5,1,2600,881
+#define WINE_PRODUCTVERSION_STR "5.1"
+
+#include "wine/wine_common_ver.rc"