Sync to Wine-20050930:
Jakob Eriksson <jakov(a)vmlinux.org>
- Get rid of HeapAlloc casts.
Robert Reif <reif(a)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(a)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(a)winehq.org>
- Build a static list of devices instead of relying on ELF
constructors.
Gerald Pfeifer <gerald(a)pfeifer.com>
- Fix compilation of the case without proper Linux joystick support.
James Dean Anderson <petr(a)pantek.org>
- Report an error if trying to get data from an unacquired mouse.
Lionel Ulmer <lionel.ulmer(a)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(a)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(a)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(a)codeweavers.com>
- Make more of the OLE interface vtables const.
Daniel Remenak <dtremenak(a)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(a)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(a)huehner.org>
- Fix some more -Wmissing-declarations warnings.
Vincent Béron <vberon(a)mecano.gme.usherb.ca>
- Use proper ifdefs around unistd.h.
Modified: trunk/reactos/lib/dinput/device.c
Modified: trunk/reactos/lib/dinput/device_private.h
Modified: trunk/reactos/lib/dinput/dinput.spec
Modified: trunk/reactos/lib/dinput/dinput.xml
Modified: trunk/reactos/lib/dinput/dinput_main.c
Modified: trunk/reactos/lib/dinput/dinput_private.h
Added: trunk/reactos/lib/dinput/effect_linuxinput.c
Modified: trunk/reactos/lib/dinput/joystick_linux.c
Modified: trunk/reactos/lib/dinput/joystick_linuxinput.c
Modified: trunk/reactos/lib/dinput/keyboard.c
Modified: trunk/reactos/lib/dinput/mouse.c
Modified: trunk/reactos/lib/dinput/regsvr.c
Modified: trunk/reactos/lib/dinput/version.rc
_____
Modified: trunk/reactos/lib/dinput/device.c
--- trunk/reactos/lib/dinput/device.c 2005-10-08 19:59:09 UTC (rev
18360)
+++ trunk/reactos/lib/dinput/device.c 2005-10-08 20:11:27 UTC (rev
18361)
@@ -464,7 +464,7 @@
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 @@
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;
}
_____
Modified: trunk/reactos/lib/dinput/device_private.h
--- trunk/reactos/lib/dinput/device_private.h 2005-10-08 19:59:09 UTC
(rev 18360)
+++ trunk/reactos/lib/dinput/device_private.h 2005-10-08 20:11:27 UTC
(rev 18361)
@@ -30,8 +30,8 @@
typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
struct IDirectInputDevice2AImpl
{
- IDirectInputDevice2AVtbl *lpVtbl;
- DWORD ref;
+ const IDirectInputDevice2AVtbl *lpVtbl;
+ LONG ref;
GUID guid;
};
_____
Modified: trunk/reactos/lib/dinput/dinput.spec
--- trunk/reactos/lib/dinput/dinput.spec 2005-10-08 19:59:09 UTC
(rev 18360)
+++ trunk/reactos/lib/dinput/dinput.spec 2005-10-08 20:11:27 UTC
(rev 18361)
@@ -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()
Property changes on: trunk/reactos/lib/dinput/dinput.spec
___________________________________________________________________
Name: svn:eol-style
+ native
_____
Modified: trunk/reactos/lib/dinput/dinput.xml
--- trunk/reactos/lib/dinput/dinput.xml 2005-10-08 19:59:09 UTC (rev
18360)
+++ trunk/reactos/lib/dinput/dinput.xml 2005-10-08 20:11:27 UTC (rev
18361)
@@ -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>
_____
Modified: trunk/reactos/lib/dinput/dinput_main.c
--- trunk/reactos/lib/dinput/dinput_main.c 2005-10-08 19:59:09 UTC
(rev 18360)
+++ trunk/reactos/lib/dinput/dinput_main.c 2005-10-08 20:11:27 UTC
(rev 18361)
@@ -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 @@
{
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 @@
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 @@
# 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 @@
# 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 @@
# 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 @@
#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 @@
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 @@
return S_OK;
}
-static IClassFactoryVtbl DICF_Vtbl = {
+static const IClassFactoryVtbl DICF_Vtbl = {
DICF_QueryInterface,
DICF_AddRef,
DICF_Release,
@@ -678,7 +678,7 @@
/***********************************************************************
* DllCanUnloadNow (DINPUT.@)
*/
-HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
+HRESULT WINAPI DllCanUnloadNow(void)
{
FIXME("(void): stub\n");
@@ -688,8 +688,7 @@
/***********************************************************************
* 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 ) ) {
_____
Modified: trunk/reactos/lib/dinput/dinput_private.h
--- trunk/reactos/lib/dinput/dinput_private.h 2005-10-08 19:59:09 UTC
(rev 18360)
+++ trunk/reactos/lib/dinput/dinput_private.h 2005-10-08 20:11:27 UTC
(rev 18361)
@@ -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;
_____
Copied: trunk/reactos/lib/dinput/effect_linuxinput.c (from rev 18360,
vendor/wine/dlls/dinput/current/effect_linuxinput.c)
Property changes on: trunk/reactos/lib/dinput/effect_linuxinput.c
___________________________________________________________________
Name: svn:keywords + Author Date Id Revision Name: svn:eol-style +
native
_____
Modified: trunk/reactos/lib/dinput/joystick_linux.c
--- trunk/reactos/lib/dinput/joystick_linux.c 2005-10-08 19:59:09 UTC
(rev 18360)
+++ trunk/reactos/lib/dinput/joystick_linux.c 2005-10-08 20:11:27 UTC
(rev 18361)
@@ -84,12 +84,12 @@
} 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 @@
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 @@
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 @@
return DI_OK;
}
-void calculate_ids(JoystickImpl* device)
+static void calculate_ids(JoystickImpl* device)
{
int i;
int axis = 0;
@@ -437,7 +436,7 @@
}
}
-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 @@
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 @@
/* 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 @@
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 @@
}
/* 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 @@
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 @@
_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 @@
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 @@
) {
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 @@
_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 @@
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 @@
return DI_OK;
}
-static IDirectInputDevice8AVtbl JoystickAvt =
+static const IDirectInputDevice8AVtbl JoystickAvt =
{
IDirectInputDevice2AImpl_QueryInterface,
IDirectInputDevice2AImpl_AddRef,
@@ -1682,7 +1681,7 @@
# define XCAST(fun) (void*)
#endif
-static IDirectInputDevice8WVtbl SysJoystickWvt =
+static const IDirectInputDevice8WVtbl SysJoystickWvt =
{
IDirectInputDevice2WImpl_QueryInterface,
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
_____
Modified: trunk/reactos/lib/dinput/joystick_linuxinput.c
--- trunk/reactos/lib/dinput/joystick_linuxinput.c 2005-10-08
19:59:09 UTC (rev 18360)
+++ trunk/reactos/lib/dinput/joystick_linuxinput.c 2005-10-08
20:11:27 UTC (rev 18361)
@@ -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 @@
#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 @@
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 @@
#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 @@
#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 @@
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 @@
(((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 @@
(((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 @@
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 @@
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 @@
{
int havejoy = 0;
- havejoy = joydev_have();
+ havejoy = joydev_have(FALSE);
if (!havejoy)
return DIERR_DEVICENOTREG;
@@ -296,7 +351,7 @@
{
int havejoy = 0;
- havejoy = joydev_have();
+ havejoy = joydev_have(FALSE);
if (!havejoy)
return DIERR_DEVICENOTREG;
@@ -338,6 +393,9 @@
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 @@
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->ab
sbits)) &&
+ 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->abs
bits)) &&
(-1!=ioctl(This->joyfd,EVIOCGBIT(EV_KEY,sizeof(This->keybits)),This->key
bits)) &&
(test_bit(This->absbits,ABS_X) &&
test_bit(This->absbits,ABS_Y) &&
(test_bit(This->keybits,BTN_TRIGGER)||
@@ -407,6 +478,30 @@
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->ffbit
s)) {
+ 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,8 +563,10 @@
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*/
if ((ret > -deadz/2 ) && (ret < deadz/2)) {
@@ -492,6 +589,8 @@
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 @@
This->js.lRz = map_axis(This,ABS_RZ,ie.value);
GEN_EVENT(DIJOFS_RZ,This->js.lRz,ie.time.tv_usec,(This->dinput->evsequen
ce)++);
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 @@
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 @@
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 @@
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 @@
) {
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
_dump_DIPROPHEADER(pdiph);
if (!HIWORD(rguid)) {
- switch ((DWORD)rguid) {
+ switch (LOWORD(rguid)) {
case (DWORD) DIPROP_BUFFERSIZE: {
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
@@ -999,7 +1135,7 @@
}
default:
- FIXME("Unknown type %ld
(%s)\n",(DWORD)rguid,debugstr_guid(rguid));
+ FIXME("Unknown type %p (%s)\n",rguid,debugstr_guid(rguid));
break;
}
}
@@ -1008,8 +1144,352 @@
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;
+}
+
[truncated at 1000 lines; 564 more skipped]