Sync to Wine-20050930:

Jakob Eriksson <jakov@vmlinux.org>
- Get rid of HeapAlloc casts.
Robert Reif <reif@earthlink.net>
- Added keyboard data format.
- Fix joystick crash when a button guid is specified in the data
  format.
  Add some parameter checking.
- Pass around real version and do correct thing based on it.
  Change cooperative level to pass on windows.
- Fix SetProperty error returned.
  Add EnumDevice joystick version check.
  Test multiple versions.
- Added dinput tests.
- Effect objects are not supported yet so don't crash when trying to
  enumerate them.
Raphael Junqueira <fenix@club-internet.fr>
- use WINE_DINPUT_KEYBOARD_MAX_KEYS instead hard-coded 256 value
- better use of critical section
- some cleanup to better understand code paths
- logic correction on SetWindowsHookExA/UnhookWindowsHookEx on
  keyboard.
Alexandre Julliard <julliard@winehq.org>
- Build a static list of devices instead of relying on ELF
  constructors.
Gerald Pfeifer <gerald@pfeifer.com>
- Fix compilation of the case without proper Linux joystick support.
James Dean Anderson <petr@pantek.org>
- Report an error if trying to get data from an unacquired mouse.
Lionel Ulmer <lionel.ulmer@free.fr>
- more pretty print for the types flag
- more Windows-aligned check for object instances
- Windows reports 0x80 on pressed buttons not 0xFF
- trace the events reported to the application
- do not flush the buffer when the application only wants to peek the
  number of elements in the queue
- trace the GetDeviceState values before they are reset
Alexandre Julliard <julliard@winehq.org>
- Added rules for building import libraries in the individual dll
  makefiles, and added support for building a .def.a static import
  library too.
- Added rules to build import libraries in the individual dll makefiles.
  Generate import libraries with the right name right away instead of
  using an intermediate .spec.def file.
- Moved config parameters to HKCU\Software\Wine\DirectInput.
- Added magic comments to all Wine-specific registry accesses to make
  them easier to grep.
- Sort entry points alphabetically.
- Removed some unused or redundant configure checks.
  A few cleanups in configure.ac.
- Don't prefix the functions DllCanUnloadNow, DllGetClassObject and
  Dll(Un)RegisterServer with the dll name so that the compiler can check
  the prototypes.
- Fixed some traces to use the right printf format and avoid typecasts.
- Use a more portable scheme for storing the name of a critical
  section.
- Use the COM macros instead of accessing lpVtbl directly.
- We are no longer generating .dbg.c files.
Marcus Meissner <marcus@jet.franken.de>
- The last argument to MultiByteToWideChar is wide character count and
  not the buffer size in bytes. Fixed all places where it was wrong.
- Fixed 3 memset()s which used the wrong size (too large).
Dmitry Timoshkov <dmitry@codeweavers.com>
- Make more of the OLE interface vtables const.
Daniel Remenak <dtremenak@gmail.com>
- Added a linux input system force feedback effect implementation.
- Allow the creation of an FF effect while the joystick is not
  acquired.
- Failing to download an effect after setting parameters is not a
  fatal error.
- Allow enumeration of objects when the device is not yet acquired.
- Flag FF-capable axes during enumeration.
- Protect FF_STATUS usage to avoid compile errors on machines with old
  linux/input.h.
- Implement EnumEffects, CreateEffect, EnumCreatedEffects,
  SendForceFeedbackCommand, and GetForceFeedbackStatus for linux input
  joysticks.
- Correct dinput handling of sliders and non-zero-based axes through the
  linux input system.
- Correctly enumerate evdev joysticks when enumeration is restricted
  with DIEDFL_FORCEFEEDBACK.
- Detect force-feedback-capable linux event device joysticks and return
  DIDC_FORCEFEEDBACK when queried for capabilities.
Mike McCormack <mike@codeweavers.com>
- Interlocked LONG* gcc warning fixes.
- gcc 4.0 warning fixes.
- gcc 4.0 warning fixes for Interlocked* functions.
- Fix warnings for no force feedback case.
Stefan Huehner <stefan@huehner.org>
- Fix some more -Wmissing-declarations warnings.
Vincent Béron <vberon@mecano.gme.usherb.ca>
- Use proper ifdefs around unistd.h.

svn path=/trunk/; revision=18361
This commit is contained in:
Gé van Geldorp 2005-10-08 20:11:27 +00:00
parent d2af8e74ef
commit 2ffd7b7d5a
13 changed files with 1570 additions and 164 deletions

View file

@ -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;
}

View file

@ -30,8 +30,8 @@
typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
struct IDirectInputDevice2AImpl
{
IDirectInputDevice2AVtbl *lpVtbl;
DWORD ref;
const IDirectInputDevice2AVtbl *lpVtbl;
LONG ref;
GUID guid;
};

View file

@ -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()

View file

@ -21,6 +21,7 @@
<file>data_formats.c</file>
<file>device.c</file>
<file>dinput_main.c</file>
<file>effect_linuxinput.c</file>
<file>joystick_linux.c</file>
<file>joystick_linuxinput.c</file>
<file>keyboard.c</file>

View file

@ -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 ) ) {

View file

@ -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;

View file

@ -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 <stdarg.h>
#include <string.h>
#ifdef HAVE_LINUX_INPUT_H
# include <linux/input.h>
#endif
#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"
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 */

View file

@ -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,

View file

@ -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 <linux/input.h>
# 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;i<ABS_MAX;i++) {
newDevice->wantmin[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;i<ABS_MAX;i++) {
if (test_bit(This->absbits,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;i<KEY_MAX;i++) if (test_bit(This->keybits,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<<i) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_ABSAXIS;
/* Linux event force feedback supports only (and always) x and y axes */
if (i == ABS_X || i == ABS_Y) {
if (This->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,

View file

@ -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,

View file

@ -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,

View file

@ -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;

View file

@ -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"