From e491e8f89792315f8ddb377ccdcea860dc3ef68d Mon Sep 17 00:00:00 2001 From: Daniel Remenak Date: Fri, 29 Jul 2005 14:18:58 +0000 Subject: [PATCH] Detect force-feedback-capable linux event device joysticks and return DIDC_FORCEFEEDBACK when queried for capabilities. --- configure | 115 ++++++++++++++++++++++++++++++ configure.ac | 5 ++ dlls/dinput/joystick_linuxinput.c | 61 ++++++++++++++-- include/config.h.in | 3 + 4 files changed, 177 insertions(+), 7 deletions(-) diff --git a/configure b/configure index bfd10f75f2d..f16079cd8d0 100755 --- a/configure +++ b/configure @@ -17574,6 +17574,121 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for struct ff_effect.direction" >&5 +echo $ECHO_N "checking for struct ff_effect.direction... $ECHO_C" >&6 +if test "${ac_cv_member_struct_ff_effect_direction+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_LINUX_INPUT_H +#include +#endif + +int +main () +{ +static struct ff_effect ac_aggr; +if (ac_aggr.direction) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_ff_effect_direction=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef HAVE_LINUX_INPUT_H +#include +#endif + +int +main () +{ +static struct ff_effect ac_aggr; +if (sizeof ac_aggr.direction) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_member_struct_ff_effect_direction=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_member_struct_ff_effect_direction=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_member_struct_ff_effect_direction" >&5 +echo "${ECHO_T}$ac_cv_member_struct_ff_effect_direction" >&6 +if test $ac_cv_member_struct_ff_effect_direction = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_FF_EFFECT_DIRECTION 1 +_ACEOF + + +fi + + echo "$as_me:$LINENO: checking for sigaddset" >&5 echo $ECHO_N "checking for sigaddset... $ECHO_C" >&6 if test "${wine_cv_have_sigaddset+set}" = set; then diff --git a/configure.ac b/configure.ac index 7e32505344e..a5dffa38467 100644 --- a/configure.ac +++ b/configure.ac @@ -1289,6 +1289,11 @@ AC_CACHE_CHECK([whether linux/input.h is for real], [Define if we have linux/input.h AND it contains the INPUT event API]) fi +AC_CHECK_MEMBERS([struct ff_effect.direction],,, +[#ifdef HAVE_LINUX_INPUT_H +#include +#endif]) + AC_CACHE_CHECK([for sigaddset],wine_cv_have_sigaddset, AC_TRY_LINK([#include ],[sigset_t set; sigaddset(&set,SIGTERM);], wine_cv_have_sigaddset=yes,wine_cv_have_sigaddset=no)) diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index 516066d599e..b46d27d4bbe 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -3,6 +3,7 @@ * Copyright 1998,2000 Marcus Meissner * Copyright 1998,1999 Lionel Ulmer * Copyright 2000-2001 TransGaming Technologies Inc. + * Copyright 2005 Daniel Remenak * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -97,6 +98,10 @@ struct JoystickImpl BOOL overflow; DIJOYSTATE2 js; + /* Force feedback variables */ + BOOL has_ff; + int num_effects; + /* data returned by the EVIOCGABS() ioctl */ int axes[ABS_MAX+1][5]; @@ -107,9 +112,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. */ @@ -379,19 +386,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 +427,30 @@ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) if (This->joyfd==-1) return DIERR_NOTFOUND; + This->has_ff = FALSE; + This->num_effects = 0; + +#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION + if (!readonly && test_bit(This->evbits, EV_FF)) { + if (-1!=ioctl(This->joyfd,EVIOCGBIT(EV_FF,sizeof(This->ffbits)),This->ffbits)) { + if (-1!=ioctl(This->joyfd,EVIOCGEFFECTS,&This->num_effects) + && This->num_effects > 0) { + This->has_ff = TRUE; + TRACE("Joystick seems to be capable of force feedback.\n"); + } + else { + TRACE("Joystick does not support any effects, disabling force feedback.\n"); + } + } + else { + TRACE("Could not get EV_FF bits; disabling force feedback.\n"); + } + } + else { + TRACE("Force feedback disabled (device is readonly or joystick incapable).\n"); + } +#endif + for (i=0;iabsbits,i)) { if (-1==ioctl(This->joyfd,EVIOCGABS(i),&(This->axes[i]))) @@ -779,6 +823,9 @@ static HRESULT WINAPI JoystickAImpl_GetCapabilities( buttons=0; for (i=0;ikeybits,i)) buttons++; + if (This->has_ff) + lpDIDevCaps->dwFlags |= DIDC_FORCEFEEDBACK; + lpDIDevCaps->dwAxes = axes; lpDIDevCaps->dwButtons = buttons; diff --git a/include/config.h.in b/include/config.h.in index 824a53f5807..03e61d8180a 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -596,6 +596,9 @@ /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP +/* Define to 1 if `direction' is member of `struct ff_effect'. */ +#undef HAVE_STRUCT_FF_EFFECT_DIRECTION + /* Define to 1 if `msg_accrights' is member of `struct msghdr'. */ #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS