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