diff --git a/configure b/configure index efdfb42d1a695b56529dc79240e84a28e43aa1d9..10bf6ccf0dc3f07bd311c8c117e039543e635c28 100755 --- a/configure +++ b/configure @@ -5584,6 +5584,7 @@ for ac_hdr in \ libutil.h \ link.h \ linux/cdrom.h \ + linux/input.h \ linux/joystick.h \ linux/ucdrom.h \ net/if.h \ @@ -5629,17 +5630,17 @@ for ac_hdr in \ do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:5633: checking for $ac_hdr" >&5 +echo "configure:5634: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5638 "configure" +#line 5639 "configure" #include "confdefs.h" #include <$ac_hdr> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5643: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5644: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5666,12 +5667,12 @@ fi done echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 -echo "configure:5670: checking whether stat file-mode macros are broken" >&5 +echo "configure:5671: checking whether stat file-mode macros are broken" >&5 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5675 "configure" +#line 5676 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/stat.h> @@ -5724,12 +5725,12 @@ fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:5728: checking for working const" >&5 +echo "configure:5729: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5733 "configure" +#line 5734 "configure" #include "confdefs.h" int main() { @@ -5778,7 +5779,7 @@ ccp = (char const *const *) p; ; return 0; } EOF -if { (eval echo configure:5782: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5783: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -5799,21 +5800,21 @@ EOF fi echo $ac_n "checking for inline""... $ac_c" 1>&6 -echo "configure:5803: checking for inline" >&5 +echo "configure:5804: checking for inline" >&5 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat > conftest.$ac_ext <<EOF -#line 5810 "configure" +#line 5811 "configure" #include "confdefs.h" int main() { } int $ac_kw foo() { ; return 0; } EOF -if { (eval echo configure:5817: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5818: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_inline=$ac_kw; break else @@ -5839,12 +5840,12 @@ EOF esac echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:5843: checking for ANSI C header files" >&5 +echo "configure:5844: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5848 "configure" +#line 5849 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> @@ -5852,7 +5853,7 @@ else #include <float.h> EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:5856: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:5857: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -5869,7 +5870,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 5873 "configure" +#line 5874 "configure" #include "confdefs.h" #include <string.h> EOF @@ -5887,7 +5888,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 5891 "configure" +#line 5892 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -5908,7 +5909,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext <<EOF -#line 5912 "configure" +#line 5913 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -5919,7 +5920,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:5923: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:5924: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -5943,12 +5944,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:5947: checking for size_t" >&5 +echo "configure:5948: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 5952 "configure" +#line 5953 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS @@ -5976,7 +5977,7 @@ EOF fi echo $ac_n "checking size of long long""... $ac_c" 1>&6 -echo "configure:5980: checking size of long long" >&5 +echo "configure:5981: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -5984,7 +5985,7 @@ else ac_cv_sizeof_long_long=0 else cat > conftest.$ac_ext <<EOF -#line 5988 "configure" +#line 5989 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -5995,7 +5996,7 @@ main() exit(0); } EOF -if { (eval echo configure:5999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6000: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_long=`cat conftestval` else @@ -6017,12 +6018,12 @@ EOF echo $ac_n "checking "whether we can use re-entrant gethostbyname_r Linux style"""... $ac_c" 1>&6 -echo "configure:6021: checking "whether we can use re-entrant gethostbyname_r Linux style"" >&5 +echo "configure:6022: checking "whether we can use re-entrant gethostbyname_r Linux style"" >&5 if eval "test \"`echo '$''{'wine_cv_linux_gethostbyname_r_6'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6026 "configure" +#line 6027 "configure" #include "confdefs.h" #include <netdb.h> @@ -6043,7 +6044,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6047: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6048: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_gethostbyname_r_6=yes else @@ -6069,12 +6070,12 @@ EOF if test "$ac_cv_header_linux_joystick_h" = "yes" then echo $ac_n "checking "whether linux/joystick.h uses the Linux 2.2+ API"""... $ac_c" 1>&6 -echo "configure:6073: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5 +echo "configure:6074: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5 if eval "test \"`echo '$''{'wine_cv_linux_joystick_22_api'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6078 "configure" +#line 6079 "configure" #include "confdefs.h" #include <sys/ioctl.h> @@ -6089,7 +6090,7 @@ int main() { /*empty*/ ; return 0; } EOF -if { (eval echo configure:6093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6094: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_linux_joystick_22_api=yes else @@ -6116,12 +6117,12 @@ fi if test "$ac_cv_header_sys_vfs_h" = "yes" then echo $ac_n "checking "whether sys/vfs.h defines statfs"""... $ac_c" 1>&6 -echo "configure:6120: checking "whether sys/vfs.h defines statfs"" >&5 +echo "configure:6121: checking "whether sys/vfs.h defines statfs"" >&5 if eval "test \"`echo '$''{'wine_cv_sys_vfs_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6125 "configure" +#line 6126 "configure" #include "confdefs.h" #include <sys/types.h> @@ -6138,7 +6139,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6142: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6143: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_vfs_has_statfs=yes else @@ -6165,12 +6166,12 @@ fi if test "$ac_cv_header_sys_statfs_h" = "yes" then echo $ac_n "checking "whether sys/statfs.h defines statfs"""... $ac_c" 1>&6 -echo "configure:6169: checking "whether sys/statfs.h defines statfs"" >&5 +echo "configure:6170: checking "whether sys/statfs.h defines statfs"" >&5 if eval "test \"`echo '$''{'wine_cv_sys_statfs_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6174 "configure" +#line 6175 "configure" #include "confdefs.h" #include <sys/types.h> @@ -6185,7 +6186,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6189: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6190: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_statfs_has_statfs=yes else @@ -6212,12 +6213,12 @@ fi if test "$ac_cv_header_sys_mount_h" = "yes" then echo $ac_n "checking "whether sys/mount.h defines statfs"""... $ac_c" 1>&6 -echo "configure:6216: checking "whether sys/mount.h defines statfs"" >&5 +echo "configure:6217: checking "whether sys/mount.h defines statfs"" >&5 if eval "test \"`echo '$''{'wine_cv_sys_mount_has_statfs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6221 "configure" +#line 6222 "configure" #include "confdefs.h" #include <sys/types.h> @@ -6232,7 +6233,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6236: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6237: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_sys_mount_has_statfs=yes else @@ -6258,7 +6259,7 @@ fi echo $ac_n "checking "for statfs.f_bfree"""... $ac_c" 1>&6 -echo "configure:6262: checking "for statfs.f_bfree"" >&5 +echo "configure:6263: checking "for statfs.f_bfree"" >&5 if eval "test \"`echo '$''{'wine_cv_statfs_bfree'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6267,7 +6268,7 @@ else wine_cv_statfs_bfree=no else cat > conftest.$ac_ext <<EOF -#line 6271 "configure" +#line 6272 "configure" #include "confdefs.h" #include <sys/types.h> @@ -6294,7 +6295,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6298: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bfree=yes else @@ -6318,7 +6319,7 @@ EOF fi echo $ac_n "checking "for statfs.f_bavail"""... $ac_c" 1>&6 -echo "configure:6322: checking "for statfs.f_bavail"" >&5 +echo "configure:6323: checking "for statfs.f_bavail"" >&5 if eval "test \"`echo '$''{'wine_cv_statfs_bavail'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6327,7 +6328,7 @@ else wine_cv_statfs_bavail=no else cat > conftest.$ac_ext <<EOF -#line 6331 "configure" +#line 6332 "configure" #include "confdefs.h" #include <sys/types.h> @@ -6354,7 +6355,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:6358: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6359: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* wine_cv_statfs_bavail=yes else @@ -6379,12 +6380,12 @@ fi echo $ac_n "checking "for msg_accrights in struct msghdr"""... $ac_c" 1>&6 -echo "configure:6383: checking "for msg_accrights in struct msghdr"" >&5 +echo "configure:6384: checking "for msg_accrights in struct msghdr"" >&5 if eval "test \"`echo '$''{'ac_cv_c_msg_accrights'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6388 "configure" +#line 6389 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/socket.h> @@ -6392,7 +6393,7 @@ int main() { struct msghdr hdr; hdr.msg_accrights=0 ; return 0; } EOF -if { (eval echo configure:6396: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_msg_accrights="yes" else @@ -6415,12 +6416,12 @@ fi echo $ac_n "checking "for sun_len in struct sockaddr_un"""... $ac_c" 1>&6 -echo "configure:6419: checking "for sun_len in struct sockaddr_un"" >&5 +echo "configure:6420: checking "for sun_len in struct sockaddr_un"" >&5 if eval "test \"`echo '$''{'ac_cv_c_sun_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6424 "configure" +#line 6425 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/socket.h> @@ -6429,7 +6430,7 @@ int main() { static struct sockaddr_un addr; addr.sun_len = 1 ; return 0; } EOF -if { (eval echo configure:6433: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:6434: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sun_len="yes" else @@ -6452,12 +6453,12 @@ fi echo $ac_n "checking "whether we need to define __i386__"""... $ac_c" 1>&6 -echo "configure:6456: checking "whether we need to define __i386__"" >&5 +echo "configure:6457: checking "whether we need to define __i386__"" >&5 if eval "test \"`echo '$''{'ac_cv_cpp_def_i386'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 6461 "configure" +#line 6462 "configure" #include "confdefs.h" #if (defined(i386) || defined(__i386)) && !defined(__i386__) yes diff --git a/configure.in b/configure.in index 7ad8c04b615fb4eedd2468057e5777f0d1517809..f309755942d3dd121c130a96770a7ae0fd223998 100644 --- a/configure.in +++ b/configure.in @@ -793,6 +793,7 @@ AC_CHECK_HEADERS(\ libutil.h \ link.h \ linux/cdrom.h \ + linux/input.h \ linux/joystick.h \ linux/ucdrom.h \ net/if.h \ diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in index 71d264d8d78f868e868059efa1f9958430e9e5a8..b0d92ab3fa628379713c04a0f9eb5cb19aa6e792 100644 --- a/dlls/dinput/Makefile.in +++ b/dlls/dinput/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ device.c \ dinput_main.c \ joystick/linux.c \ + joystick/linuxinput.c \ keyboard/main.c \ mouse/main.c diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 6f4380421c1141547d41ce5b54c81c4f554a092d..01eab8976b29e8ce9be116837084490c97693038 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -33,7 +33,7 @@ static ICOM_VTABLE(IDirectInputA) ddiavt; static ICOM_VTABLE(IDirectInput7A) ddi7avt; /* This array will be filled a dinput.so loading */ -#define MAX_WINE_DINPUT_DEVICES 3 +#define MAX_WINE_DINPUT_DEVICES 4 static dinput_device * dinput_devices[MAX_WINE_DINPUT_DEVICES]; static int nrof_dinput_devices = 0; @@ -41,7 +41,20 @@ static int nrof_dinput_devices = 0; * the ELF startup initialisation at this point. */ void dinput_register_device(dinput_device *device) { - dinput_devices[nrof_dinput_devices++] = device; + int i; + + /* insert according to priority */ + for (i=0;i<nrof_dinput_devices;i++) { + if (dinput_devices[i]->pref <= device->pref) { + memcpy(dinput_devices+i+1,dinput_devices+i,sizeof(dinput_devices[0])*(nrof_dinput_devices-i)); + dinput_devices[i] = device; + break; + } + } + if (i==nrof_dinput_devices) /* not found, or too low priority */ + dinput_devices[nrof_dinput_devices] = device; + + nrof_dinput_devices++; /* increase MAX_DDRAW_DRIVERS if the line below triggers */ assert(nrof_dinput_devices <= MAX_WINE_DINPUT_DEVICES); diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index 869f4a7da08a8ec26e9f387a4e5dfb5028a18bd1..3aff85d79a6750570b6bd8a03c7a580477e16ff4 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -17,6 +17,7 @@ struct IDirectInputAImpl /* Function called by all devices that Wine supports */ typedef struct dinput_device { + INT pref; BOOL (*enum_device)(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi); HRESULT (*create_device)(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev); } dinput_device; diff --git a/dlls/dinput/joystick/linux.c b/dlls/dinput/joystick/linux.c index 988ef28fa23394812ab6d6604c540ae3eda25fc7..48b4ce115298daf5aeb031fd4f500d0fc13ca062 100644 --- a/dlls/dinput/joystick/linux.c +++ b/dlls/dinput/joystick/linux.c @@ -72,7 +72,7 @@ static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf static BOOL joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi) { - if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) { + if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) { /* check whether we have a joystick */ if ((access(JOYDEV,O_RDONLY) != -1) || (errno!=ENODEV && errno!=ENOENT)) { TRACE("Enumerating the Joystick device\n"); @@ -81,7 +81,8 @@ static BOOL joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTAN lpddi->guidInstance = GUID_Joystick; lpddi->guidProduct = DInput_Wine_Joystick_GUID; /* we only support traditional joysticks for now */ - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL; + lpddi->dwDevType = DIDEVTYPE_JOYSTICK | + (DIDEVTYPEJOYSTICK_TRADITIONAL<<8); strcpy(lpddi->tszInstanceName, "Joystick"); /* ioctl JSIOCGNAME(len) */ strcpy(lpddi->tszProductName, "Wine Joystick"); @@ -131,6 +132,7 @@ static HRESULT joydev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, RE } static dinput_device joydev = { + 10, joydev_enum_device, joydev_create_device }; diff --git a/dlls/dinput/joystick/linuxinput.c b/dlls/dinput/joystick/linuxinput.c new file mode 100644 index 0000000000000000000000000000000000000000..179b99d0db6ac0c1c1506361679af02de835e553 --- /dev/null +++ b/dlls/dinput/joystick/linuxinput.c @@ -0,0 +1,885 @@ +/* DirectInput Joystick device + * + * Copyright 1998,2000 Marcus Meissner + * Copyright 1998,1999 Lionel Ulmer + * + */ + +#include "config.h" + +#ifdef HAVE_LINUX_INPUT_H + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/time.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <errno.h> +#ifdef HAVE_SYS_ERRNO_H +# include <sys/errno.h> +#endif +#ifdef HAVE_LINUX_INPUT_H +# include <linux/input.h> +#endif + +#define EVDEVPREFIX "/dev/input/event" + +#include "debugtools.h" +#include "winbase.h" +#include "winerror.h" +#include "windef.h" +#include "dinput.h" + +#include "dinput_private.h" +#include "device_private.h" + +DEFAULT_DEBUG_CHANNEL(dinput); + +/* Wine joystick driver object instances */ +#define WINE_JOYSTICK_AXIS_BASE 0 +#define WINE_JOYSTICK_BUTTON_BASE 8 + +typedef struct JoystickAImpl JoystickAImpl; +static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt; +static ICOM_VTABLE(IDirectInputDevice7A) Joystick7Avt; +struct JoystickAImpl +{ + /* IDirectInputDevice2AImpl */ + ICOM_VFIELD(IDirectInputDevice2A); + DWORD ref; + GUID guid; + + + /* The 'parent' DInput */ + IDirectInputAImpl *dinput; + + /* joystick private */ + /* what range and deadzone the game wants */ + LONG wantmin[ABS_MAX]; + LONG wantmax[ABS_MAX]; + LONG deadz[ABS_MAX]; + + /* autodetecting ranges per axe by following movement */ + LONG havemax[ABS_MAX]; + LONG havemin[ABS_MAX]; + + int joyfd; + + LPDIDATAFORMAT df; + HANDLE hEvent; + LPDIDEVICEOBJECTDATA data_queue; + int queue_pos, queue_len; + DIJOYSTATE js; + + /* data returned by the EVIOCGABS() ioctl */ + int axes[ABS_MAX+1][5]; + +#define AXE_ABS 0 +#define AXE_ABSMIN 1 +#define AXE_ABSMAX 2 +#define AXE_ABSFUZZ 3 +#define AXE_ABSFLAT 4 + + + /* data returned by EVIOCGBIT for EV_ABS and EV_KEY */ + BYTE absbits[(ABS_MAX+7)/8]; + BYTE keybits[(KEY_MAX+7)/8]; +}; + +/* This GUID is slightly different from the linux joystick one. Take note. */ +static GUID DInput_Wine_Joystick_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */ + 0x9e573eda, + 0x7734, + 0x11d2, + {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} +}; + +#define test_bit(arr,bit) (((BYTE*)arr)[bit>>3]&(1<<(bit&7))) + +static BOOL joydev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi) +{ + int i, fd, havejoy = 0; + + if ((dwDevType != 0) && (GET_DIDEVICE_TYPE(dwDevType) != DIDEVTYPE_JOYSTICK)) + return FALSE; + + for (i=0;i<64;i++) { + char buf[200]; + BYTE absbits[(ABS_MAX+7)/8],keybits[(KEY_MAX+7)/8]; + + sprintf(buf,EVDEVPREFIX"%d",i); + if (-1!=(fd=open(buf,O_RDONLY))) { + if (-1==ioctl(fd,EVIOCGBIT(EV_ABS,sizeof(absbits)),absbits)) { + perror("EVIOCGBIT EV_ABS"); + close(fd); + continue; + } + if (-1==ioctl(fd,EVIOCGBIT(EV_KEY,sizeof(keybits)),keybits)) { + perror("EVIOCGBIT EV_KEY"); + 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) && + ( test_bit(keybits,BTN_TRIGGER) || + test_bit(keybits,BTN_A) || + test_bit(keybits,BTN_1) + ) + ) { + FIXME("found a joystick at %s!\n",buf); + havejoy = 1; + } + close(fd); + } + if (havejoy || (errno==ENODEV)) + break; + } + + if (!havejoy) + return FALSE; + + TRACE("Enumerating the Joystick device\n"); + + /* Return joystick */ + lpddi->guidInstance = GUID_Joystick; + lpddi->guidProduct = DInput_Wine_Joystick_GUID; + + lpddi->dwDevType = DIDEVTYPE_JOYSTICK | + (DIDEVTYPEJOYSTICK_TRADITIONAL<<8); + + strcpy(lpddi->tszInstanceName, "Joystick"); + /* ioctl JSIOCGNAME(len) */ + strcpy(lpddi->tszProductName, "Wine Joystick"); + return TRUE; +} + +static JoystickAImpl *alloc_device(REFGUID rguid, ICOM_VTABLE(IDirectInputDevice2A) *jvt, IDirectInputAImpl *dinput) +{ + JoystickAImpl* newDevice; + int i; + + newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl)); + newDevice->ref = 1; + ICOM_VTBL(newDevice) = jvt; + + newDevice->joyfd = -1; + newDevice->dinput = dinput; + memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); + for (i=0;i<ABS_MAX;i++) { + newDevice->wantmin[i] = -32768; + newDevice->wantmax[i] = 32767; + newDevice->deadz[i] = 1024; /* guessing */ + } + return newDevice; +} + +static HRESULT joydev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev) +{ + if ((IsEqualGUID(&GUID_Joystick,rguid)) || + (IsEqualGUID(&DInput_Wine_Joystick_GUID,rguid))) { + if ((riid == NULL) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid))) { + *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &JoystickAvt, dinput); + + TRACE("Creating a Joystick device (%p)\n", *pdev); + return DI_OK; + } else if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) { + *pdev=(IDirectInputDeviceA*) alloc_device(rguid, (ICOM_VTABLE(IDirectInputDevice2A) *) &Joystick7Avt, dinput); + + TRACE("Creating a Joystick DInput7A device (%p)\n", *pdev); + return DI_OK; + } else + return DIERR_NOINTERFACE; + } + + return DIERR_DEVICENOTREG; +} + +static dinput_device joydev = { + 20, + joydev_enum_device, + joydev_create_device +}; + +DECL_GLOBAL_CONSTRUCTOR(joydev_register) { dinput_register_device(&joydev); } + +/****************************************************************************** + * Joystick + */ +static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface) +{ + ICOM_THIS(JoystickAImpl,iface); + + This->ref--; + if (This->ref) + return This->ref; + + /* Free the data queue */ + if (This->data_queue != NULL) + HeapFree(GetProcessHeap(),0,This->data_queue); + + /* Free the DataFormat */ + HeapFree(GetProcessHeap(), 0, This->df); + + HeapFree(GetProcessHeap(),0,This); + return 0; +} + +/****************************************************************************** + * SetDataFormat : the application can choose the format of the data + * the device driver sends back with GetDeviceState. + */ +static HRESULT WINAPI JoystickAImpl_SetDataFormat( + LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df +) +{ + ICOM_THIS(JoystickAImpl,iface); + int i; + + TRACE("(this=%p,%p)\n",This,df); + + TRACE("(df.dwSize=%ld)\n",df->dwSize); + TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize); + TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags); + TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize); + TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs); + + for (i=0;i<df->dwNumObjs;i++) { + TRACE("df.rgodf[%d].guid %s (%p)\n",i,debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid); + TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs); + TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType)); + TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags); + } + + /* Store the new data format */ + This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize); + memcpy(This->df, df, df->dwSize); + This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize); + memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize); + + return 0; +} + +/****************************************************************************** + * Acquire : gets exclusive control of the joystick + */ +static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface) +{ + int i; + ICOM_THIS(JoystickAImpl,iface); + char buf[200]; + + 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!=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)|| + test_bit(This->keybits,BTN_A) || + test_bit(This->keybits,BTN_1) + ) + ) + ) + break; + close(This->joyfd); + This->joyfd = -1; + } + if (This->joyfd==-1) + return DIERR_NOTFOUND; + + for (i=0;i<ABS_MAX;i++) { + if (test_bit(This->absbits,i)) { + if (-1==ioctl(This->joyfd,EVIOCGABS(i),&(This->axes[i]))) + continue; + FIXME("axe %d: cur=%d, min=%d, max=%d, fuzz=%d, flat=%d\n", + i, + This->axes[i][AXE_ABS], + This->axes[i][AXE_ABSMIN], + This->axes[i][AXE_ABSMAX], + This->axes[i][AXE_ABSFUZZ], + This->axes[i][AXE_ABSFLAT] + ); + This->havemax[i] = This->axes[i][AXE_ABSMIN]; + This->havemin[i] = This->axes[i][AXE_ABSMAX]; + } + } + MESSAGE("\n"); + + return 0; +} + +/****************************************************************************** + * Unacquire : frees the joystick + */ +static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface) +{ + ICOM_THIS(JoystickAImpl,iface); + + TRACE("(this=%p)\n",This); + if (This->joyfd!=-1) { + close(This->joyfd); + This->joyfd = -1; + } + return DI_OK; +} + +/* + * This maps the read value (from the input event) to a value in the + * 'wanted' range. It also autodetects the possible range of the axe and + * adapts values accordingly. + */ +static int +map_axis(JoystickAImpl* This, int axis, int val) { + int xmid = This->axes[axis][AXE_ABS]; + int xmin = This->axes[axis][AXE_ABSMIN]; + int xmax = This->axes[axis][AXE_ABSMAX]; + int hmax = This->havemax[axis]; + int hmin = This->havemin[axis]; + int wmin = This->wantmin[axis]; + int wmax = This->wantmax[axis]; + int ret; + + if (val > hmax) This->havemax[axis] = hmax = val; + if (val < hmin) This->havemin[axis] = hmin = val; + + if (xmin == xmax) return val; + if ((hmin == hmax) || (hmax==xmid) || (hmin==xmid)) return val; + + /* dont assume total linearity, but linearity starting from a zeropoint */ + if (val > xmid) { + ret = (val-xmid)*((wmax-wmin)/2)/(hmax-xmid)+0; + } else { + ret = (xmid-val)*((wmax-wmin)/2)/(hmin-xmid)+0; + } + +#if 0 + /* deadzone doesn't work comfortably enough right now. needs more testing*/ + if ((ret > -deadz/2 ) && (ret < deadz/2)) { + FIXME("%d in deadzone, return mid.\n",val); + return (wmax-wmin)/2+wmin; + } +#endif + return ret; +} + +static void joy_polldev(JoystickAImpl *This) { + struct timeval tv; + fd_set readfds; + struct input_event ie; + + if (This->joyfd==-1) + return; + + while (1) { + memset(&tv,0,sizeof(tv)); + FD_ZERO(&readfds); + FD_SET(This->joyfd,&readfds); + + if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv)) + return; + + /* we have one event, so we can read */ + if (sizeof(ie)!=read(This->joyfd,&ie,sizeof(ie))) + return; + + TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value); + switch (ie.type) { + case EV_KEY: /* button */ + switch (ie.code) { + case BTN_TRIGGER: /* normal flight stick */ + case BTN_A: /* gamepad */ + case BTN_1: /* generic */ + GEN_EVENT(DIJOFS_BUTTON(0),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.rgbButtons[0] = ie.value?0x80:0x00; + break; + case BTN_THUMB: + case BTN_B: + case BTN_2: + GEN_EVENT(DIJOFS_BUTTON(1),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.rgbButtons[1] = ie.value?0x80:0x00; + break; + case BTN_THUMB2: + case BTN_C: + case BTN_3: + GEN_EVENT(DIJOFS_BUTTON(2),ie.value?0x80:0x0,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.rgbButtons[2] = ie.value?0x80:0x00; + break; + default: + FIXME("unhandled joystick axe %x, value %d\n",ie.code,ie.value); + break; + } + break; + case EV_ABS: + switch (ie.code) { + case ABS_X: + GEN_EVENT(DIJOFS_X,ie.value,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.lX = map_axis(This,0,ie.value); + break; + case ABS_Y: + GEN_EVENT(DIJOFS_Y,ie.value,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.lY = map_axis(This,1,ie.value); + case ABS_Z: + GEN_EVENT(DIJOFS_Z,ie.value,ie.time.tv_usec,(This->dinput->evsequence)++); + This->js.lZ = map_axis(This,2,ie.value); + break; + default: + FIXME("unhandled joystick axe event (code %d, value %d)\n",ie.code,ie.value); + break; + } + break; + default: + FIXME("joystick cannot handle type %d event (code %d)\n",ie.type,ie.code); + break; + } + } +} + +/****************************************************************************** + * GetDeviceState : returns the "state" of the joystick. + * + */ +static HRESULT WINAPI JoystickAImpl_GetDeviceState( + LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr +) { + ICOM_THIS(JoystickAImpl,iface); + + joy_polldev(This); + + TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr); + if (len != sizeof(DIJOYSTATE)) { + FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len); + } + memcpy(ptr,&(This->js),len); + This->queue_pos = 0; + return 0; +} + +/****************************************************************************** + * GetDeviceData : gets buffered input data. + */ +static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface, + DWORD dodsize, + LPDIDEVICEOBJECTDATA dod, + LPDWORD entries, + DWORD flags +) { + ICOM_THIS(JoystickAImpl,iface); + + FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags); + + joy_polldev(This); + if (flags & DIGDD_PEEK) + FIXME("DIGDD_PEEK\n"); + + if (dod == NULL) { + } else { + } + return 0; +} + +/****************************************************************************** + * SetProperty : change input device properties + */ +static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface, + REFGUID rguid, + LPCDIPROPHEADER ph) +{ + ICOM_THIS(JoystickAImpl,iface); + + FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); + 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) { + case (DWORD) DIPROP_BUFFERSIZE: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + + FIXME("buffersize = %ld\n",pd->dwData); + break; + } + case (DWORD)DIPROP_RANGE: { + LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph; + + FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax); + switch (ph->dwObj) { + case 0: /* X */ + case 4: /* Y */ + case 8: /* Z */ + case 12: /* Rx */ + case 16: /* Ry */ + case 20: /* Rz */ + This->wantmin[ph->dwObj/4] = pr->lMin; + This->wantmax[ph->dwObj/4] = pr->lMax; + break; + default: + FIXME("setting proprange %ld - %ld for dwObj %ld\n",pr->lMin,pr->lMax,ph->dwObj); + } + break; + } + case (DWORD)DIPROP_DEADZONE: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + + FIXME("setting deadzone(%ld)\n",pd->dwData); + This->deadz[ph->dwObj/4] = pd->dwData; + break; + } + default: + FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid)); + break; + } + } + return 0; +} + +/****************************************************************************** + * SetEventNotification : specifies event to be sent on state change + */ +static HRESULT WINAPI JoystickAImpl_SetEventNotification( + LPDIRECTINPUTDEVICE2A iface, HANDLE hnd +) { + ICOM_THIS(JoystickAImpl,iface); + + TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd); + This->hEvent = hnd; + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_GetCapabilities( + LPDIRECTINPUTDEVICE2A iface, + LPDIDEVCAPS lpDIDevCaps) +{ + ICOM_THIS(JoystickAImpl,iface); + int xfd = This->joyfd; + int i,axes,buttons; + int wasacquired = 1; + + TRACE("%p->(%p)\n",iface,lpDIDevCaps); + if (xfd==-1) { + /* yes, games assume we return something, even if unacquired */ + JoystickAImpl_Acquire(iface); + xfd = This->joyfd; + wasacquired = 0; + } + lpDIDevCaps->dwFlags = DIDC_ATTACHED; + lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK; + + axes=0; + for (i=0;i<ABS_MAX;i++) if (test_bit(This->absbits,i)) axes++; + buttons=0; + for (i=0;i<KEY_MAX;i++) if (test_bit(This->keybits,i)) buttons++; + + lpDIDevCaps->dwAxes = axes; + lpDIDevCaps->dwButtons = buttons; + + if (!wasacquired) + JoystickAImpl_Unacquire(iface); + + return DI_OK; +} + +static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) { + ICOM_THIS(JoystickAImpl,iface); + TRACE("(),stub!\n"); + + joy_polldev(This); + return DI_OK; +} + +/****************************************************************************** + * EnumObjects : enumerate the different buttons and axis... + */ +static HRESULT WINAPI JoystickAImpl_EnumObjects( + LPDIRECTINPUTDEVICE2A iface, + LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, + LPVOID lpvRef, + DWORD dwFlags) +{ + ICOM_THIS(JoystickAImpl,iface); + DIDEVICEOBJECTINSTANCEA ddoi; + int xfd = This->joyfd; + + + TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags); + if (TRACE_ON(dinput)) { + DPRINTF(" - flags = "); + _dump_EnumObjects_flags(dwFlags); + DPRINTF("\n"); + } + + if (xfd == -1) return DIERR_NOTACQUIRED; + + /* Only the fields till dwFFMaxForce are relevant */ + ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce); + + /* For the joystick, do as is done in the GetCapabilities function */ + /* FIXME: needs more items */ + if ((dwFlags == DIDFT_ALL) || + (dwFlags & DIDFT_AXIS)) { + BYTE i; + + for (i = 0; i < ABS_MAX; i++) { + if (!test_bit(This->absbits,i)) continue; + + switch (i) { + case ABS_X: + ddoi.guidType = GUID_XAxis; + ddoi.dwOfs = DIJOFS_X; + break; + case ABS_Y: + ddoi.guidType = GUID_YAxis; + ddoi.dwOfs = DIJOFS_Y; + break; + case ABS_Z: + ddoi.guidType = GUID_ZAxis; + ddoi.dwOfs = DIJOFS_Z; + break; + case ABS_RX: + ddoi.guidType = GUID_RxAxis; + ddoi.dwOfs = DIJOFS_RX; + break; + case ABS_RY: + ddoi.guidType = GUID_RyAxis; + ddoi.dwOfs = DIJOFS_RY; + break; + case ABS_RZ: + ddoi.guidType = GUID_RzAxis; + ddoi.dwOfs = DIJOFS_RZ; + break; + case ABS_THROTTLE: + ddoi.guidType = GUID_Slider; + ddoi.dwOfs = DIJOFS_SLIDER(0); + break; + default: + FIXME("unhandled abs axis %d, ignoring!\n",i); + } + ddoi.dwType = DIDFT_MAKEINSTANCE((1<<i) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_ABSAXIS; + sprintf(ddoi.tszName, "%d-Axis", i); + _dump_OBJECTINSTANCEA(&ddoi); + if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) + return DI_OK; + } + } + + if ((dwFlags == DIDFT_ALL) || + (dwFlags & DIDFT_BUTTON)) { + BYTE i; + + /*The DInput SDK says that GUID_Button is only for mouse buttons but well*/ + + ddoi.guidType = GUID_Button; + + for (i = 0; i < KEY_MAX; i++) { + if (!test_bit(This->keybits,i)) continue; + + switch (i) { + case BTN_TRIGGER: + case BTN_A: + case BTN_1: + ddoi.dwOfs = DIJOFS_BUTTON(0); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 0) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_THUMB: + case BTN_B: + case BTN_2: + ddoi.dwOfs = DIJOFS_BUTTON(1); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 1) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_THUMB2: + case BTN_C: + case BTN_3: + ddoi.dwOfs = DIJOFS_BUTTON(2); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 2) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_TOP: + case BTN_X: + case BTN_4: + ddoi.dwOfs = DIJOFS_BUTTON(3); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 3) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_TOP2: + case BTN_Y: + case BTN_5: + ddoi.dwOfs = DIJOFS_BUTTON(4); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 4) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_PINKIE: + case BTN_Z: + case BTN_6: + ddoi.dwOfs = DIJOFS_BUTTON(5); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 5) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_BASE: + case BTN_TL: + case BTN_7: + ddoi.dwOfs = DIJOFS_BUTTON(6); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 6) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_BASE2: + case BTN_TR: + case BTN_8: + ddoi.dwOfs = DIJOFS_BUTTON(7); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 7) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_BASE3: + case BTN_TL2: + case BTN_9: + ddoi.dwOfs = DIJOFS_BUTTON(8); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 8) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_BASE4: + case BTN_TR2: + ddoi.dwOfs = DIJOFS_BUTTON(9); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 9) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + case BTN_BASE5: + case BTN_SELECT: + ddoi.dwOfs = DIJOFS_BUTTON(10); + ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << 10) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON; + break; + } + sprintf(ddoi.tszName, "%d-Button", i); + _dump_OBJECTINSTANCEA(&ddoi); + if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) + return DI_OK; + } + } + + if (xfd!=This->joyfd) + close(xfd); + + return DI_OK; +} + +/****************************************************************************** + * GetProperty : get input device properties + */ +static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface, + REFGUID rguid, + LPDIPROPHEADER pdiph) +{ + ICOM_THIS(JoystickAImpl,iface); + + TRACE("(this=%p,%s,%p): stub!\n", + iface, debugstr_guid(rguid), pdiph); + + if (TRACE_ON(dinput)) + _dump_DIPROPHEADER(pdiph); + + if (!HIWORD(rguid)) { + switch ((DWORD)rguid) { + case (DWORD) DIPROP_BUFFERSIZE: { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + + TRACE(" return buffersize = %d\n",This->queue_len); + pd->dwData = This->queue_len; + break; + } + + case (DWORD) DIPROP_RANGE: { + LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph; + if ((pdiph->dwHow == DIPH_BYID) && + (pdiph->dwObj & DIDFT_ABSAXIS)) { + /* The app is querying the current range of the axis : return the lMin and lMax values */ + FIXME("unimplemented axis range query.\n"); + } + + break; + } + + default: + FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid)); + break; + } + } + + + return DI_OK; +} + +static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IDirectInputDevice2AImpl_QueryInterface, + IDirectInputDevice2AImpl_AddRef, + JoystickAImpl_Release, + JoystickAImpl_GetCapabilities, + JoystickAImpl_EnumObjects, + JoystickAImpl_GetProperty, + JoystickAImpl_SetProperty, + JoystickAImpl_Acquire, + JoystickAImpl_Unacquire, + JoystickAImpl_GetDeviceState, + JoystickAImpl_GetDeviceData, + JoystickAImpl_SetDataFormat, + JoystickAImpl_SetEventNotification, + IDirectInputDevice2AImpl_SetCooperativeLevel, + IDirectInputDevice2AImpl_GetObjectInfo, + IDirectInputDevice2AImpl_GetDeviceInfo, + IDirectInputDevice2AImpl_RunControlPanel, + IDirectInputDevice2AImpl_Initialize, + IDirectInputDevice2AImpl_CreateEffect, + IDirectInputDevice2AImpl_EnumEffects, + IDirectInputDevice2AImpl_GetEffectInfo, + IDirectInputDevice2AImpl_GetForceFeedbackState, + IDirectInputDevice2AImpl_SendForceFeedbackCommand, + IDirectInputDevice2AImpl_EnumCreatedEffectObjects, + IDirectInputDevice2AImpl_Escape, + JoystickAImpl_Poll, + IDirectInputDevice2AImpl_SendDeviceData, +}; + +#if !defined(__STRICT_ANSI__) && defined(__GNUC__) +# define XCAST(fun) (typeof(Joystick7Avt.fn##fun)) +#else +# define XCAST(fun) (void*) +#endif + +static ICOM_VTABLE(IDirectInputDevice7A) Joystick7Avt = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + XCAST(QueryInterface)IDirectInputDevice2AImpl_QueryInterface, + XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, + XCAST(Release)JoystickAImpl_Release, + XCAST(GetCapabilities)JoystickAImpl_GetCapabilities, + XCAST(EnumObjects)JoystickAImpl_EnumObjects, + XCAST(GetProperty)JoystickAImpl_GetProperty, + XCAST(SetProperty)JoystickAImpl_SetProperty, + XCAST(Acquire)JoystickAImpl_Acquire, + XCAST(Unacquire)JoystickAImpl_Unacquire, + XCAST(GetDeviceState)JoystickAImpl_GetDeviceState, + XCAST(GetDeviceData)JoystickAImpl_GetDeviceData, + XCAST(SetDataFormat)JoystickAImpl_SetDataFormat, + XCAST(SetEventNotification)JoystickAImpl_SetEventNotification, + XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel, + XCAST(GetObjectInfo)IDirectInputDevice2AImpl_GetObjectInfo, + XCAST(GetDeviceInfo)IDirectInputDevice2AImpl_GetDeviceInfo, + XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel, + XCAST(Initialize)IDirectInputDevice2AImpl_Initialize, + XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect, + XCAST(EnumEffects)IDirectInputDevice2AImpl_EnumEffects, + XCAST(GetEffectInfo)IDirectInputDevice2AImpl_GetEffectInfo, + XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState, + XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand, + XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects, + XCAST(Escape)IDirectInputDevice2AImpl_Escape, + XCAST(Poll)JoystickAImpl_Poll, + XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData, + IDirectInputDevice7AImpl_EnumEffectsInFile, + IDirectInputDevice7AImpl_WriteEffectToFile +}; + +#undef XCAST + +#endif /* HAVE_LINUX_INPUT_H */ diff --git a/dlls/dinput/keyboard/main.c b/dlls/dinput/keyboard/main.c index ac37258352858f7ad026504b6f68fb2565b92a8c..df171db9f2f04a36fe1615ce59f03c65fc31a932 100644 --- a/dlls/dinput/keyboard/main.c +++ b/dlls/dinput/keyboard/main.c @@ -105,6 +105,7 @@ static HRESULT keyboarddev_create_device(IDirectInputAImpl *dinput, REFGUID rgui } static dinput_device keyboarddev = { + 100, keyboarddev_enum_device, keyboarddev_create_device }; diff --git a/dlls/dinput/mouse/main.c b/dlls/dinput/mouse/main.c index 62e673b5347d9992d07a4ec026ce61d130adb57b..83c6d23fe67ec78342d2b25320ae847fe7a75d6c 100644 --- a/dlls/dinput/mouse/main.c +++ b/dlls/dinput/mouse/main.c @@ -199,6 +199,7 @@ static HRESULT mousedev_create_device(IDirectInputAImpl *dinput, REFGUID rguid, } static dinput_device mousedev = { + 100, mousedev_enum_device, mousedev_create_device }; diff --git a/include/config.h.in b/include/config.h.in index 5d011548cb843d0172509801e33c813053b436fe..4e4ee3f4faa5f2497324670c410d737fee2871e7 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -329,6 +329,9 @@ /* Define if you have the <linux/cdrom.h> header file. */ #undef HAVE_LINUX_CDROM_H +/* Define if you have the <linux/input.h> header file. */ +#undef HAVE_LINUX_INPUT_H + /* Define if you have the <linux/joystick.h> header file. */ #undef HAVE_LINUX_JOYSTICK_H diff --git a/include/dinput.h b/include/dinput.h index 42a8db6feef6e5ea0a39d9143b0eb189c19b7035..456441e906190fc786715933da1af3fa4b46d572 100644 --- a/include/dinput.h +++ b/include/dinput.h @@ -175,6 +175,9 @@ DECL_WINELIB_TYPE_AW(LPDIRECTINPUTDEVICE2) #define DIDEVTYPEJOYSTICK_WHEEL 6 #define DIDEVTYPEJOYSTICK_HEADTRACKER 7 +#define GET_DIDEVICE_TYPE(dwDevType) LOBYTE(dwDevType) +#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType) + typedef struct { DWORD dwSize; GUID guidType;