mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 19:26:33 +00:00
add wine dinput and dinput8 it have been modify to working in windows and reactos. when reactos got hooks implant remove all #ifdef __REACTOS__ and code that belong it compelete, then remove all #ifndef __REACTOS__ to geting in working in reactos and windows. dxguid comes from mingw with some modify todo rewrite dection code of keyboard, mouse, joystick to using windows registers to get what type of hardware. Limit Only keyboard are working in reactos for moment. svn path=/trunk/; revision=11864
1716 lines
53 KiB
C
1716 lines
53 KiB
C
/* DirectInput Joystick device
|
|
*
|
|
* Copyright 1998 Marcus Meissner
|
|
* Copyright 1998,1999 Lionel Ulmer
|
|
* Copyright 2000-2001 TransGaming Technologies Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
/*
|
|
* To Do:
|
|
* dead zone
|
|
* force feedback
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "wine/port.h"
|
|
|
|
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
# include <unistd.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_TIME_H
|
|
# include <sys/time.h>
|
|
#endif
|
|
#include <sys/fcntl.h>
|
|
#ifdef HAVE_SYS_IOCTL_H
|
|
# include <sys/ioctl.h>
|
|
#endif
|
|
#include <errno.h>
|
|
#ifdef HAVE_SYS_ERRNO_H
|
|
# include <sys/errno.h>
|
|
#endif
|
|
#ifdef HAVE_LINUX_IOCTL_H
|
|
# include <linux/ioctl.h>
|
|
#endif
|
|
#ifdef HAVE_LINUX_JOYSTICK_H
|
|
# include <linux/joystick.h>
|
|
#endif
|
|
#define JOYDEV "/dev/js"
|
|
|
|
#include "wine/debug.h"
|
|
#include "wine/unicode.h"
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winerror.h"
|
|
#include "winreg.h"
|
|
#include "dinput.h"
|
|
|
|
#include "dinput_private.h"
|
|
#include "device_private.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
|
|
|
|
typedef struct {
|
|
LONG lMin;
|
|
LONG lMax;
|
|
LONG lDeadZone;
|
|
LONG lSaturation;
|
|
} ObjProps;
|
|
|
|
typedef struct {
|
|
LONG lX;
|
|
LONG lY;
|
|
} POV;
|
|
|
|
typedef struct JoystickImpl JoystickImpl;
|
|
static IDirectInputDevice8AVtbl JoystickAvt;
|
|
static IDirectInputDevice8WVtbl JoystickWvt;
|
|
struct JoystickImpl
|
|
{
|
|
LPVOID lpVtbl;
|
|
DWORD ref;
|
|
GUID guid;
|
|
char dev[32];
|
|
|
|
/* The 'parent' DInput */
|
|
IDirectInputImpl *dinput;
|
|
|
|
/* joystick private */
|
|
int joyfd;
|
|
DIJOYSTATE2 js; /* wine data */
|
|
LPDIDATAFORMAT user_df; /* user defined format */
|
|
DataFormat *transform; /* wine to user format converter */
|
|
int *offsets; /* object offsets */
|
|
ObjProps *props;
|
|
HANDLE hEvent;
|
|
LPDIDEVICEOBJECTDATA data_queue;
|
|
int queue_head, queue_tail, queue_len;
|
|
BOOL acquired;
|
|
char *name;
|
|
DIDEVCAPS devcaps;
|
|
LONG deadzone;
|
|
int *axis_map;
|
|
int axes;
|
|
int buttons;
|
|
POV povs[4];
|
|
CRITICAL_SECTION crit;
|
|
BOOL overflow;
|
|
};
|
|
|
|
static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
|
|
0x9e573ed9,
|
|
0x7734,
|
|
0x11d2,
|
|
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
|
|
};
|
|
|
|
static void _dump_DIDEVCAPS(LPDIDEVCAPS lpDIDevCaps)
|
|
{
|
|
TRACE("dwSize: %ld\n", lpDIDevCaps->dwSize);
|
|
TRACE("dwFlags: %08lx\n",lpDIDevCaps->dwFlags);
|
|
TRACE("dwDevType: %08lx %s\n", lpDIDevCaps->dwDevType,
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_DEVICE ? "DIDEVTYPE_DEVICE" :
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_MOUSE ? "DIDEVTYPE_MOUSE" :
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_KEYBOARD ? "DIDEVTYPE_KEYBOARD" :
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_JOYSTICK ? "DIDEVTYPE_JOYSTICK" :
|
|
lpDIDevCaps->dwDevType == DIDEVTYPE_HID ? "DIDEVTYPE_HID" : "UNKNOWN");
|
|
TRACE("dwAxes: %ld\n",lpDIDevCaps->dwAxes);
|
|
TRACE("dwButtons: %ld\n",lpDIDevCaps->dwButtons);
|
|
TRACE("dwPOVs: %ld\n",lpDIDevCaps->dwPOVs);
|
|
if (lpDIDevCaps->dwSize > sizeof(DIDEVCAPS_DX3)) {
|
|
TRACE("dwFFSamplePeriod: %ld\n",lpDIDevCaps->dwFFSamplePeriod);
|
|
TRACE("dwFFMinTimeResolution: %ld\n",lpDIDevCaps->dwFFMinTimeResolution);
|
|
TRACE("dwFirmwareRevision: %ld\n",lpDIDevCaps->dwFirmwareRevision);
|
|
TRACE("dwHardwareRevision: %ld\n",lpDIDevCaps->dwHardwareRevision);
|
|
TRACE("dwFFDriverVersion: %ld\n",lpDIDevCaps->dwFFDriverVersion);
|
|
}
|
|
}
|
|
|
|
static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id)
|
|
{
|
|
int fd = -1;
|
|
char dev[32];
|
|
|
|
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
|
WARN("force feedback not supported\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) {
|
|
/* check whether we have a joystick */
|
|
sprintf(dev, "%s%d", JOYDEV, id);
|
|
if ((fd = open(dev,O_RDONLY)) < 0) {
|
|
WARN("open(%s,O_RDONLY) failed: %s\n", dev, strerror(errno));
|
|
return FALSE;
|
|
}
|
|
|
|
/* Return joystick */
|
|
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
|
|
lpddi->guidInstance.Data3 = id;
|
|
lpddi->guidProduct = DInput_Wine_Joystick_GUID;
|
|
/* we only support traditional joysticks for now */
|
|
if (version >= 8)
|
|
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
|
else
|
|
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
|
sprintf(lpddi->tszInstanceName, "Joystick %d", id);
|
|
#if defined(JSIOCGNAME)
|
|
if (ioctl(fd,JSIOCGNAME(sizeof(lpddi->tszProductName)),lpddi->tszProductName) < 0) {
|
|
WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", dev, strerror(errno));
|
|
strcpy(lpddi->tszProductName, "Wine Joystick");
|
|
}
|
|
#else
|
|
strcpy(lpddi->tszProductName, "Wine Joystick");
|
|
#endif
|
|
|
|
lpddi->guidFFDriver = GUID_NULL;
|
|
close(fd);
|
|
TRACE("Enumerating the linux Joystick device: %s (%s)\n", dev, lpddi->tszProductName);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id)
|
|
{
|
|
int fd = -1;
|
|
char name[MAX_PATH];
|
|
char dev[32];
|
|
char friendly[32];
|
|
|
|
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
|
WARN("force feedback not supported\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if ((dwDevType==0) || (GET_DIDEVICE_TYPE(dwDevType)==DIDEVTYPE_JOYSTICK)) {
|
|
/* check whether we have a joystick */
|
|
sprintf(dev, "%s%d", JOYDEV, id);
|
|
if ((fd = open(dev,O_RDONLY)) < 0) {
|
|
WARN("open(%s,O_RDONLY) failed: %s\n", dev, strerror(errno));
|
|
return FALSE;
|
|
}
|
|
|
|
/* Return joystick */
|
|
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
|
|
lpddi->guidInstance.Data3 = id;
|
|
lpddi->guidProduct = DInput_Wine_Joystick_GUID;
|
|
/* we only support traditional joysticks for now */
|
|
if (version >= 8)
|
|
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
|
else
|
|
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
|
sprintf(friendly, "Joystick %d", id);
|
|
MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
|
|
#if defined(JSIOCGNAME)
|
|
if (ioctl(fd,JSIOCGNAME(sizeof(name)),name) < 0) {
|
|
WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", dev, strerror(errno));
|
|
strcpy(name, "Wine Joystick");
|
|
}
|
|
#else
|
|
strcpy(name, "Wine Joystick");
|
|
#endif
|
|
MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
|
|
lpddi->guidFFDriver = GUID_NULL;
|
|
close(fd);
|
|
TRACE("Enumerating the linux Joystick device: %s (%s)\n",dev,name);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Get a config key from either the app-specific or the default config
|
|
*/
|
|
|
|
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 ))
|
|
return 0;
|
|
|
|
if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, buffer, &size ))
|
|
return 0;
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
/*
|
|
* Setup the dinput options.
|
|
*/
|
|
|
|
static HRESULT setup_dinput_options(JoystickImpl * device)
|
|
{
|
|
char buffer[MAX_PATH+1];
|
|
HKEY hkey, appkey = 0;
|
|
DWORD len;
|
|
|
|
buffer[MAX_PATH]='\0';
|
|
|
|
if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\dinput", &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 );
|
|
}
|
|
}
|
|
|
|
/* get options */
|
|
|
|
if (!get_config_key( hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH )) {
|
|
device->deadzone = atoi(buffer);
|
|
TRACE("setting default deadzone to: \"%s\" %ld\n", buffer, device->deadzone);
|
|
}
|
|
|
|
if (!get_config_key( hkey, appkey, device->name, buffer, MAX_PATH )) {
|
|
int tokens = 0;
|
|
int axis = 0;
|
|
int pov = 0;
|
|
char *delim = ",";
|
|
char * ptr;
|
|
TRACE("\"%s\" = \"%s\"\n", device->name, buffer);
|
|
|
|
device->axis_map = HeapAlloc(GetProcessHeap(), 0, device->axes * sizeof(int));
|
|
if (device->axis_map == 0)
|
|
return DIERR_OUTOFMEMORY;
|
|
|
|
if ((ptr = strtok(buffer, delim)) != NULL) {
|
|
do {
|
|
if (strcmp(ptr, "X") == 0) {
|
|
device->axis_map[tokens] = 0;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Y") == 0) {
|
|
device->axis_map[tokens] = 1;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Z") == 0) {
|
|
device->axis_map[tokens] = 2;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Rx") == 0) {
|
|
device->axis_map[tokens] = 3;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Ry") == 0) {
|
|
device->axis_map[tokens] = 4;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Rz") == 0) {
|
|
device->axis_map[tokens] = 5;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Slider1") == 0) {
|
|
device->axis_map[tokens] = 6;
|
|
axis++;
|
|
} else if (strcmp(ptr, "Slider2") == 0) {
|
|
device->axis_map[tokens] = 7;
|
|
axis++;
|
|
} else if (strcmp(ptr, "POV1") == 0) {
|
|
device->axis_map[tokens++] = 8;
|
|
device->axis_map[tokens] = 8;
|
|
pov++;
|
|
} else if (strcmp(ptr, "POV2") == 0) {
|
|
device->axis_map[tokens++] = 9;
|
|
device->axis_map[tokens] = 9;
|
|
pov++;
|
|
} else if (strcmp(ptr, "POV3") == 0) {
|
|
device->axis_map[tokens++] = 10;
|
|
device->axis_map[tokens] = 10;
|
|
pov++;
|
|
} else if (strcmp(ptr, "POV4") == 0) {
|
|
device->axis_map[tokens++] = 11;
|
|
device->axis_map[tokens] = 11;
|
|
pov++;
|
|
} else {
|
|
ERR("invalid joystick axis type: %s\n", ptr);
|
|
device->axis_map[tokens] = tokens;
|
|
axis++;
|
|
}
|
|
|
|
tokens++;
|
|
} while ((ptr = strtok(NULL, delim)) != NULL);
|
|
|
|
if (tokens != device->devcaps.dwAxes) {
|
|
ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n", device->axes, axis, pov,tokens);
|
|
while (tokens < device->axes) {
|
|
device->axis_map[tokens] = tokens;
|
|
tokens++;
|
|
}
|
|
}
|
|
}
|
|
|
|
device->devcaps.dwAxes = axis;
|
|
device->devcaps.dwPOVs = pov;
|
|
}
|
|
|
|
if (appkey)
|
|
RegCloseKey( appkey );
|
|
|
|
if (hkey)
|
|
RegCloseKey( hkey );
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
void calculate_ids(JoystickImpl* device)
|
|
{
|
|
int i;
|
|
int axis = 0;
|
|
int button = 0;
|
|
int pov = 0;
|
|
int axis_base;
|
|
int pov_base;
|
|
int button_base;
|
|
|
|
/* Make two passes over the format. The first counts the number
|
|
* for each type and the second sets the id */
|
|
for (i = 0; i < device->user_df->dwNumObjs; i++) {
|
|
if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_AXIS)
|
|
axis++;
|
|
else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_POV)
|
|
pov++;
|
|
else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_BUTTON)
|
|
button++;
|
|
}
|
|
|
|
axis_base = 0;
|
|
pov_base = axis;
|
|
button_base = axis + pov;
|
|
|
|
axis = 0;
|
|
button = 0;
|
|
pov = 0;
|
|
|
|
for (i = 0; i < device->user_df->dwNumObjs; i++) {
|
|
DWORD type = 0;
|
|
if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_AXIS) {
|
|
axis++;
|
|
type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
|
|
DIDFT_MAKEINSTANCE(axis + axis_base);
|
|
TRACE("axis type = 0x%08lx\n", type);
|
|
} else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_POV) {
|
|
pov++;
|
|
type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
|
|
DIDFT_MAKEINSTANCE(pov + pov_base);
|
|
TRACE("POV type = 0x%08lx\n", type);
|
|
} else if (DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) & DIDFT_BUTTON) {
|
|
button++;
|
|
type = DIDFT_GETTYPE(device->user_df->rgodf[i].dwType) |
|
|
DIDFT_MAKEINSTANCE(button + button_base);
|
|
TRACE("button type = 0x%08lx\n", type);
|
|
}
|
|
device->user_df->rgodf[i].dwType = type;
|
|
}
|
|
}
|
|
|
|
static HRESULT alloc_device(REFGUID rguid, LPVOID jvt, IDirectInputImpl *dinput, LPDIRECTINPUTDEVICEA* pdev)
|
|
{
|
|
DWORD i;
|
|
JoystickImpl* newDevice;
|
|
char name[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
|
|
if (newDevice == 0) {
|
|
WARN("out of memory\n");
|
|
*pdev = 0;
|
|
return DIERR_OUTOFMEMORY;
|
|
}
|
|
|
|
sprintf(newDevice->dev, "%s%d", JOYDEV, rguid->Data3);
|
|
|
|
if ((newDevice->joyfd = open(newDevice->dev,O_RDONLY)) < 0) {
|
|
WARN("open(%s,O_RDONLY) failed: %s\n", newDevice->dev, strerror(errno));
|
|
HeapFree(GetProcessHeap(), 0, newDevice);
|
|
return DIERR_DEVICENOTREG;
|
|
}
|
|
|
|
/* get the device name */
|
|
#if defined(JSIOCGNAME)
|
|
if (ioctl(newDevice->joyfd,JSIOCGNAME(MAX_PATH),name) < 0) {
|
|
WARN("ioctl(%s,JSIOCGNAME) failed: %s\n", newDevice->dev, strerror(errno));
|
|
strcpy(name, "Wine Joystick");
|
|
}
|
|
#else
|
|
strcpy(name, "Wine Joystick");
|
|
#endif
|
|
|
|
/* copy the device name */
|
|
newDevice->name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
|
|
strcpy(newDevice->name, name);
|
|
|
|
#ifdef JSIOCGAXES
|
|
if (ioctl(newDevice->joyfd,JSIOCGAXES,&newDevice->axes) < 0) {
|
|
WARN("ioctl(%s,JSIOCGAXES) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
|
|
newDevice->axes = 2;
|
|
}
|
|
#endif
|
|
#ifdef JSIOCGBUTTONS
|
|
if (ioctl(newDevice->joyfd,JSIOCGBUTTONS,&newDevice->buttons) < 0) {
|
|
WARN("ioctl(%s,JSIOCGBUTTONS) failed: %s, defauting to 2\n", newDevice->dev, strerror(errno));
|
|
newDevice->buttons = 2;
|
|
}
|
|
#endif
|
|
|
|
newDevice->lpVtbl = jvt;
|
|
newDevice->ref = 1;
|
|
newDevice->dinput = dinput;
|
|
newDevice->acquired = FALSE;
|
|
newDevice->overflow = FALSE;
|
|
CopyMemory(&(newDevice->guid),rguid,sizeof(*rguid));
|
|
|
|
/* setup_dinput_options may change these */
|
|
newDevice->deadzone = 5000;
|
|
newDevice->devcaps.dwButtons = newDevice->buttons;
|
|
newDevice->devcaps.dwAxes = newDevice->axes;
|
|
newDevice->devcaps.dwPOVs = 0;
|
|
|
|
/* do any user specified configuration */
|
|
hr = setup_dinput_options(newDevice);
|
|
if (hr != DI_OK)
|
|
goto FAILED1;
|
|
|
|
if (newDevice->axis_map == 0) {
|
|
newDevice->axis_map = HeapAlloc(GetProcessHeap(), 0, newDevice->axes * sizeof(int));
|
|
if (newDevice->axis_map == 0)
|
|
goto FAILED;
|
|
|
|
for (i = 0; i < newDevice->axes; i++)
|
|
newDevice->axis_map[i] = i;
|
|
}
|
|
|
|
/* wine uses DIJOYSTATE2 as it's internal format so copy
|
|
* the already defined format c_dfDIJoystick2 */
|
|
newDevice->user_df = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwSize);
|
|
if (newDevice->user_df == 0)
|
|
goto FAILED;
|
|
|
|
CopyMemory(newDevice->user_df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
|
|
|
|
/* copy default objects */
|
|
newDevice->user_df->rgodf = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwNumObjs*c_dfDIJoystick2.dwObjSize);
|
|
if (newDevice->user_df->rgodf == 0)
|
|
goto FAILED;
|
|
|
|
CopyMemory(newDevice->user_df->rgodf,c_dfDIJoystick2.rgodf,c_dfDIJoystick2.dwNumObjs*c_dfDIJoystick2.dwObjSize);
|
|
|
|
/* create default properties */
|
|
newDevice->props = HeapAlloc(GetProcessHeap(),0,c_dfDIJoystick2.dwNumObjs*sizeof(ObjProps));
|
|
if (newDevice->props == 0)
|
|
goto FAILED;
|
|
|
|
/* initialize default properties */
|
|
for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
|
|
newDevice->props[i].lMin = 0;
|
|
newDevice->props[i].lMax = 0xffff;
|
|
newDevice->props[i].lDeadZone = newDevice->deadzone; /* % * 1000 */
|
|
newDevice->props[i].lSaturation = 0;
|
|
}
|
|
|
|
/* create an offsets array */
|
|
newDevice->offsets = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,c_dfDIJoystick2.dwNumObjs*sizeof(int));
|
|
if (newDevice->offsets == 0)
|
|
goto FAILED;
|
|
|
|
/* create the default transform filter */
|
|
newDevice->transform = create_DataFormat(&c_dfDIJoystick2, newDevice->user_df, newDevice->offsets);
|
|
|
|
calculate_ids(newDevice);
|
|
|
|
IDirectInputDevice_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
|
|
InitializeCriticalSection(&(newDevice->crit));
|
|
newDevice->crit.DebugInfo->Spare[1] = (DWORD)"DINPUT_Mouse";
|
|
|
|
newDevice->devcaps.dwSize = sizeof(newDevice->devcaps);
|
|
newDevice->devcaps.dwFlags = DIDC_ATTACHED;
|
|
newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK;
|
|
newDevice->devcaps.dwFFSamplePeriod = 0;
|
|
newDevice->devcaps.dwFFMinTimeResolution = 0;
|
|
newDevice->devcaps.dwFirmwareRevision = 0;
|
|
newDevice->devcaps.dwHardwareRevision = 0;
|
|
newDevice->devcaps.dwFFDriverVersion = 0;
|
|
|
|
if (TRACE_ON(dinput)) {
|
|
_dump_DIDATAFORMAT(newDevice->user_df);
|
|
for (i = 0; i < (newDevice->axes); i++)
|
|
TRACE("axis_map[%ld] = %d\n", i, newDevice->axis_map[i]);
|
|
_dump_DIDEVCAPS(&newDevice->devcaps);
|
|
}
|
|
|
|
*pdev = (LPDIRECTINPUTDEVICEA)newDevice;
|
|
|
|
return DI_OK;
|
|
|
|
FAILED:
|
|
hr = DIERR_OUTOFMEMORY;
|
|
FAILED1:
|
|
if (newDevice->axis_map)
|
|
HeapFree(GetProcessHeap(),0,newDevice->axis_map);
|
|
if (newDevice->name)
|
|
HeapFree(GetProcessHeap(),0,newDevice->name);
|
|
if (newDevice->props)
|
|
HeapFree(GetProcessHeap(),0,newDevice->props);
|
|
if (newDevice->user_df->rgodf)
|
|
HeapFree(GetProcessHeap(),0,newDevice->user_df->rgodf);
|
|
if (newDevice->user_df)
|
|
HeapFree(GetProcessHeap(),0,newDevice->user_df);
|
|
if (newDevice)
|
|
HeapFree(GetProcessHeap(),0,newDevice);
|
|
*pdev = 0;
|
|
|
|
return hr;
|
|
}
|
|
|
|
static BOOL IsJoystickGUID(REFGUID guid)
|
|
{
|
|
GUID wine_joystick = DInput_Wine_Joystick_GUID;
|
|
GUID dev_guid = *guid;
|
|
|
|
wine_joystick.Data3 = 0;
|
|
dev_guid.Data3 = 0;
|
|
|
|
return IsEqualGUID(&wine_joystick, &dev_guid);
|
|
}
|
|
|
|
static HRESULT joydev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
|
|
{
|
|
if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
|
|
(IsJoystickGUID(rguid))) {
|
|
if ((riid == NULL) ||
|
|
IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
|
|
return alloc_device(rguid, &JoystickAvt, dinput, pdev);
|
|
} else {
|
|
WARN("no interface\n");
|
|
*pdev = 0;
|
|
return DIERR_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
WARN("invalid device GUID\n");
|
|
*pdev = 0;
|
|
return DIERR_DEVICENOTREG;
|
|
}
|
|
|
|
static HRESULT joydev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
|
|
{
|
|
if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
|
|
(IsJoystickGUID(rguid))) {
|
|
if ((riid == NULL) ||
|
|
IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
|
|
IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
|
|
return alloc_device(rguid, &JoystickWvt, dinput, (LPDIRECTINPUTDEVICEA *)pdev);
|
|
} else {
|
|
WARN("no interface\n");
|
|
*pdev = 0;
|
|
return DIERR_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
WARN("invalid device GUID\n");
|
|
*pdev = 0;
|
|
return DIERR_DEVICENOTREG;
|
|
}
|
|
|
|
static dinput_device joydev = {
|
|
10,
|
|
"Wine Linux joystick driver",
|
|
joydev_enum_deviceA,
|
|
joydev_enum_deviceW,
|
|
joydev_create_deviceA,
|
|
joydev_create_deviceW
|
|
};
|
|
|
|
DECL_GLOBAL_CONSTRUCTOR(joydev_register) { dinput_register_device(&joydev); }
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* Joystick
|
|
*/
|
|
static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
ULONG ref;
|
|
|
|
ref = InterlockedDecrement((&This->ref));
|
|
if (ref)
|
|
return ref;
|
|
|
|
/* Free the device name */
|
|
if (This->name)
|
|
HeapFree(GetProcessHeap(),0,This->name);
|
|
|
|
/* Free the axis map */
|
|
if (This->axis_map)
|
|
HeapFree(GetProcessHeap(),0,This->axis_map);
|
|
|
|
/* Free the data queue */
|
|
if (This->data_queue != NULL)
|
|
HeapFree(GetProcessHeap(),0,This->data_queue);
|
|
|
|
/* Free the DataFormat */
|
|
HeapFree(GetProcessHeap(), 0, This->user_df->rgodf);
|
|
HeapFree(GetProcessHeap(), 0, This->user_df);
|
|
|
|
/* Free the properties */
|
|
HeapFree(GetProcessHeap(), 0, This->props);
|
|
|
|
/* Free the offsets array */
|
|
HeapFree(GetProcessHeap(),0,This->offsets);
|
|
|
|
/* release the data transform filter */
|
|
release_DataFormat(This->transform);
|
|
|
|
This->crit.DebugInfo->Spare[1] = 0;
|
|
DeleteCriticalSection(&(This->crit));
|
|
IDirectInputDevice_Release((LPDIRECTINPUTDEVICE8A)This->dinput);
|
|
|
|
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(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
LPCDIDATAFORMAT df)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
unsigned int i;
|
|
LPDIDATAFORMAT new_df = 0;
|
|
LPDIOBJECTDATAFORMAT new_rgodf = 0;
|
|
ObjProps * new_props = 0;
|
|
|
|
TRACE("(%p,%p)\n",This,df);
|
|
|
|
if (This->acquired) {
|
|
WARN("acquired\n");
|
|
return DIERR_ACQUIRED;
|
|
}
|
|
|
|
if (TRACE_ON(dinput))
|
|
_dump_DIDATAFORMAT(df);
|
|
|
|
/* Store the new data format */
|
|
new_df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
|
|
if (new_df == 0)
|
|
goto FAILED;
|
|
|
|
new_rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
|
|
if (new_rgodf == 0)
|
|
goto FAILED;
|
|
|
|
new_props = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*sizeof(ObjProps));
|
|
if (new_props == 0)
|
|
goto FAILED;
|
|
|
|
HeapFree(GetProcessHeap(),0,This->user_df);
|
|
HeapFree(GetProcessHeap(),0,This->user_df->rgodf);
|
|
HeapFree(GetProcessHeap(),0,This->props);
|
|
release_DataFormat(This->transform);
|
|
|
|
This->user_df = new_df;
|
|
CopyMemory(This->user_df, df, df->dwSize);
|
|
This->user_df->rgodf = new_rgodf;
|
|
CopyMemory(This->user_df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
|
|
This->props = new_props;
|
|
for (i = 0; i < df->dwNumObjs; i++) {
|
|
This->props[i].lMin = 0;
|
|
This->props[i].lMax = 0xffff;
|
|
This->props[i].lDeadZone = 1000;
|
|
This->props[i].lSaturation = 0;
|
|
}
|
|
This->transform = create_DataFormat(&c_dfDIJoystick2, This->user_df, This->offsets);
|
|
|
|
calculate_ids(This);
|
|
|
|
return DI_OK;
|
|
|
|
FAILED:
|
|
WARN("out of memory\n");
|
|
if (new_props)
|
|
HeapFree(GetProcessHeap(),0,new_props);
|
|
if (new_rgodf)
|
|
HeapFree(GetProcessHeap(),0,new_rgodf);
|
|
if (new_df)
|
|
HeapFree(GetProcessHeap(),0,new_df);
|
|
return DIERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Acquire : gets exclusive control of the joystick
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
if (This->acquired) {
|
|
WARN("already acquired\n");
|
|
return S_FALSE;
|
|
}
|
|
|
|
/* open the joystick device */
|
|
if (This->joyfd==-1) {
|
|
TRACE("opening joystick device %s\n", This->dev);
|
|
|
|
This->joyfd=open(This->dev,O_RDONLY);
|
|
if (This->joyfd==-1) {
|
|
ERR("open(%s) failed: %s\n", This->dev, strerror(errno));
|
|
return DIERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
This->acquired = TRUE;
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Unacquire : frees the joystick
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
if (!This->acquired) {
|
|
WARN("not acquired\n");
|
|
return DIERR_NOTACQUIRED;
|
|
}
|
|
|
|
if (This->joyfd!=-1) {
|
|
TRACE("closing joystick device\n");
|
|
close(This->joyfd);
|
|
This->joyfd = -1;
|
|
This->acquired = FALSE;
|
|
return DI_OK;
|
|
}
|
|
|
|
This->acquired = FALSE;
|
|
|
|
return DI_NOEFFECT;
|
|
}
|
|
|
|
LONG map_axis(JoystickImpl * This, short val, short index)
|
|
{
|
|
double fval = val;
|
|
double fmin = This->props[index].lMin;
|
|
double fmax = This->props[index].lMax;
|
|
double fret;
|
|
|
|
fret = (((fval + 32767.0) * (fmax - fmin)) / (32767.0*2.0)) + fmin;
|
|
|
|
if (fret >= 0.0)
|
|
fret += 0.5;
|
|
else
|
|
fret -= 0.5;
|
|
|
|
return fret;
|
|
}
|
|
|
|
/* convert wine format offset to user format object index */
|
|
int offset_to_object(JoystickImpl *This, int offset)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++) {
|
|
if (This->user_df->rgodf[i].dwOfs == offset)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static LONG calculate_pov(JoystickImpl *This, int index)
|
|
{
|
|
if (This->povs[index].lX < 16384) {
|
|
if (This->povs[index].lY < 16384)
|
|
This->js.rgdwPOV[index] = 31500;
|
|
else if (This->povs[index].lY > 49150)
|
|
This->js.rgdwPOV[index] = 22500;
|
|
else
|
|
This->js.rgdwPOV[index] = 27000;
|
|
} else if (This->povs[index].lX > 49150) {
|
|
if (This->povs[index].lY < 16384)
|
|
This->js.rgdwPOV[index] = 4500;
|
|
else if (This->povs[index].lY > 49150)
|
|
This->js.rgdwPOV[index] = 13500;
|
|
else
|
|
This->js.rgdwPOV[index] = 9000;
|
|
} else {
|
|
if (This->povs[index].lY < 16384)
|
|
This->js.rgdwPOV[index] = 0;
|
|
else if (This->povs[index].lY > 49150)
|
|
This->js.rgdwPOV[index] = 18000;
|
|
else
|
|
This->js.rgdwPOV[index] = -1;
|
|
}
|
|
|
|
return This->js.rgdwPOV[index];
|
|
}
|
|
|
|
static void joy_polldev(JoystickImpl *This) {
|
|
struct timeval tv;
|
|
fd_set readfds;
|
|
struct js_event jse;
|
|
TRACE("(%p)\n", This);
|
|
|
|
if (This->joyfd==-1) {
|
|
WARN("no device\n");
|
|
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(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
|
|
return;
|
|
}
|
|
TRACE("js_event: type 0x%x, number %d, value %d\n",
|
|
jse.type,jse.number,jse.value);
|
|
if (jse.type & JS_EVENT_BUTTON) {
|
|
int offset = This->offsets[jse.number + 12];
|
|
int value = jse.value?0x80:0x00;
|
|
|
|
This->js.rgbButtons[jse.number] = value;
|
|
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
|
|
} else if (jse.type & JS_EVENT_AXIS) {
|
|
int number = This->axis_map[jse.number]; /* wine format object index */
|
|
if (number < 12) {
|
|
int offset = This->offsets[number];
|
|
int index = offset_to_object(This, offset);
|
|
LONG value = map_axis(This, jse.value, index);
|
|
|
|
/* FIXME do deadzone and saturation here */
|
|
|
|
TRACE("changing axis %d => %d\n", jse.number, number);
|
|
switch (number) {
|
|
case 0:
|
|
This->js.lX = value;
|
|
break;
|
|
case 1:
|
|
This->js.lY = value;
|
|
break;
|
|
case 2:
|
|
This->js.lZ = value;
|
|
break;
|
|
case 3:
|
|
This->js.lRx = value;
|
|
break;
|
|
case 4:
|
|
This->js.lRy = value;
|
|
break;
|
|
case 5:
|
|
This->js.lRz = value;
|
|
break;
|
|
case 6:
|
|
This->js.rglSlider[0] = value;
|
|
break;
|
|
case 7:
|
|
This->js.rglSlider[1] = value;
|
|
break;
|
|
case 8:
|
|
/* FIXME don't go off array */
|
|
if (This->axis_map[jse.number + 1] == number)
|
|
This->povs[0].lX = value;
|
|
else if (This->axis_map[jse.number - 1] == number)
|
|
This->povs[0].lY = value;
|
|
value = calculate_pov(This, 0);
|
|
break;
|
|
case 9:
|
|
if (This->axis_map[jse.number + 1] == number)
|
|
This->povs[1].lX = value;
|
|
else if (This->axis_map[jse.number - 1] == number)
|
|
This->povs[1].lY = value;
|
|
value = calculate_pov(This, 1);
|
|
break;
|
|
case 10:
|
|
if (This->axis_map[jse.number + 1] == number)
|
|
This->povs[2].lX = value;
|
|
else if (This->axis_map[jse.number - 1] == number)
|
|
This->povs[2].lY = value;
|
|
value = calculate_pov(This, 2);
|
|
break;
|
|
case 11:
|
|
if (This->axis_map[jse.number + 1] == number)
|
|
This->povs[3].lX = value;
|
|
else if (This->axis_map[jse.number - 1] == number)
|
|
This->povs[3].lY = value;
|
|
value = calculate_pov(This, 3);
|
|
break;
|
|
}
|
|
|
|
GEN_EVENT(offset,value,jse.time,(This->dinput->evsequence)++);
|
|
} else
|
|
WARN("axis %d not supported\n", number);
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetDeviceState : returns the "state" of the joystick.
|
|
*
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_GetDeviceState(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
DWORD len,
|
|
LPVOID ptr)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p,0x%08lx,%p)\n",This,len,ptr);
|
|
|
|
if (!This->acquired) {
|
|
WARN("not acquired\n");
|
|
return DIERR_NOTACQUIRED;
|
|
}
|
|
|
|
/* update joystick state */
|
|
joy_polldev(This);
|
|
|
|
/* convert and copy data to user supplied buffer */
|
|
fill_DataFormat(ptr, &This->js, This->transform);
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetDeviceData : gets buffered input data.
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_GetDeviceData(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
DWORD dodsize,
|
|
LPDIDEVICEOBJECTDATA dod,
|
|
LPDWORD entries,
|
|
DWORD flags)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
DWORD len;
|
|
int nqtail;
|
|
HRESULT hr = DI_OK;
|
|
|
|
TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
|
|
|
|
if (!This->acquired) {
|
|
WARN("not acquired\n");
|
|
return DIERR_NOTACQUIRED;
|
|
}
|
|
|
|
EnterCriticalSection(&(This->crit));
|
|
|
|
joy_polldev(This);
|
|
|
|
len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0)
|
|
+ (This->queue_head - This->queue_tail);
|
|
if (len > *entries)
|
|
len = *entries;
|
|
|
|
if (dod == NULL) {
|
|
if (len)
|
|
TRACE("Application discarding %ld event(s).\n", len);
|
|
|
|
*entries = len;
|
|
nqtail = This->queue_tail + len;
|
|
while (nqtail >= This->queue_len)
|
|
nqtail -= This->queue_len;
|
|
} else {
|
|
if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) {
|
|
ERR("Wrong structure size !\n");
|
|
LeaveCriticalSection(&(This->crit));
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
if (len)
|
|
TRACE("Application retrieving %ld event(s).\n", len);
|
|
|
|
*entries = 0;
|
|
nqtail = This->queue_tail;
|
|
while (len) {
|
|
DWORD span = ((This->queue_head < nqtail) ? This->queue_len : This->queue_head) - nqtail;
|
|
if (span > len)
|
|
span = len;
|
|
|
|
/* Copy the buffered data into the application queue */
|
|
memcpy(dod + *entries, This->data_queue + nqtail, span * dodsize);
|
|
/* Advance position */
|
|
nqtail += span;
|
|
if (nqtail >= This->queue_len)
|
|
nqtail -= This->queue_len;
|
|
*entries += span;
|
|
len -= span;
|
|
}
|
|
}
|
|
|
|
if (This->overflow) {
|
|
hr = DI_BUFFEROVERFLOW;
|
|
if (!(flags & DIGDD_PEEK)) {
|
|
This->overflow = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!(flags & DIGDD_PEEK))
|
|
This->queue_tail = nqtail;
|
|
|
|
LeaveCriticalSection(&(This->crit));
|
|
|
|
return hr;
|
|
}
|
|
|
|
int find_property(JoystickImpl * This, LPCDIPROPHEADER ph)
|
|
{
|
|
int i;
|
|
if (ph->dwHow == DIPH_BYOFFSET) {
|
|
return offset_to_object(This, ph->dwObj);
|
|
} else if (ph->dwHow == DIPH_BYID) {
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++) {
|
|
if ((This->user_df->rgodf[i].dwType & 0x00ffffff) == (ph->dwObj & 0x00ffffff)) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* SetProperty : change input device properties
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_SetProperty(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
REFGUID rguid,
|
|
LPCDIPROPHEADER ph)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
int i;
|
|
|
|
TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
|
|
|
|
if (TRACE_ON(dinput))
|
|
_dump_DIPROPHEADER(ph);
|
|
|
|
if (!HIWORD(rguid)) {
|
|
switch ((DWORD)rguid) {
|
|
case (DWORD) DIPROP_BUFFERSIZE: {
|
|
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
|
TRACE("buffersize = %ld\n",pd->dwData);
|
|
if (This->data_queue)
|
|
This->data_queue = HeapReAlloc(GetProcessHeap(),0, This->data_queue, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
|
|
else
|
|
This->data_queue = HeapAlloc(GetProcessHeap(),0, pd->dwData * sizeof(DIDEVICEOBJECTDATA));
|
|
This->queue_head = 0;
|
|
This->queue_tail = 0;
|
|
This->queue_len = pd->dwData;
|
|
break;
|
|
}
|
|
case (DWORD)DIPROP_RANGE: {
|
|
LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
|
|
if (ph->dwHow == DIPH_DEVICE) {
|
|
TRACE("proprange(%ld,%ld) all\n",pr->lMin,pr->lMax);
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++) {
|
|
This->props[i].lMin = pr->lMin;
|
|
This->props[i].lMax = pr->lMax;
|
|
}
|
|
} else {
|
|
int obj = find_property(This, ph);
|
|
TRACE("proprange(%ld,%ld) obj=%d\n",pr->lMin,pr->lMax,obj);
|
|
if (obj >= 0) {
|
|
This->props[obj].lMin = pr->lMin;
|
|
This->props[obj].lMax = pr->lMax;
|
|
return DI_OK;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case (DWORD)DIPROP_DEADZONE: {
|
|
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
|
if (ph->dwHow == DIPH_DEVICE) {
|
|
TRACE("deadzone(%ld) all\n",pd->dwData);
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++)
|
|
This->props[i].lDeadZone = pd->dwData;
|
|
} else {
|
|
int obj = find_property(This, ph);
|
|
TRACE("deadzone(%ld) obj=%d\n",pd->dwData,obj);
|
|
if (obj >= 0) {
|
|
This->props[obj].lDeadZone = pd->dwData;
|
|
return DI_OK;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case (DWORD)DIPROP_SATURATION: {
|
|
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
|
if (ph->dwHow == DIPH_DEVICE) {
|
|
TRACE("saturation(%ld) all\n",pd->dwData);
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++)
|
|
This->props[i].lSaturation = pd->dwData;
|
|
} else {
|
|
int obj = find_property(This, ph);
|
|
TRACE("saturation(%ld) obj=%d\n",pd->dwData,obj);
|
|
if (obj >= 0) {
|
|
This->props[obj].lSaturation = pd->dwData;
|
|
return DI_OK;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* SetEventNotification : specifies event to be sent on state change
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_SetEventNotification(
|
|
LPDIRECTINPUTDEVICE8A iface, HANDLE hnd
|
|
) {
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
|
|
This->hEvent = hnd;
|
|
return DI_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI JoystickAImpl_GetCapabilities(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
LPDIDEVCAPS lpDIDevCaps)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
int size;
|
|
|
|
TRACE("%p->(%p)\n",iface,lpDIDevCaps);
|
|
|
|
if (lpDIDevCaps == NULL) {
|
|
WARN("invalid parameter: lpDIDevCaps = NULL\n");
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
size = lpDIDevCaps->dwSize;
|
|
CopyMemory(lpDIDevCaps, &This->devcaps, size);
|
|
lpDIDevCaps->dwSize = size;
|
|
|
|
if (TRACE_ON(dinput))
|
|
_dump_DIDEVCAPS(lpDIDevCaps);
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p)\n",This);
|
|
|
|
if (!This->acquired) {
|
|
WARN("not acquired\n");
|
|
return DIERR_NOTACQUIRED;
|
|
}
|
|
|
|
joy_polldev(This);
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* EnumObjects : enumerate the different buttons and axis...
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_EnumObjects(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
|
|
LPVOID lpvRef,
|
|
DWORD dwFlags)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
DIDEVICEOBJECTINSTANCEA ddoi;
|
|
BYTE i;
|
|
int user_offset;
|
|
int user_object;
|
|
|
|
TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
|
|
if (TRACE_ON(dinput)) {
|
|
TRACE(" - flags = ");
|
|
_dump_EnumObjects_flags(dwFlags);
|
|
TRACE("\n");
|
|
}
|
|
|
|
/* Only the fields till dwFFMaxForce are relevant */
|
|
ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
|
|
|
|
/* For the joystick, do as is done in the GetCapabilities function */
|
|
if ((dwFlags == DIDFT_ALL) ||
|
|
(dwFlags & DIDFT_AXIS) ||
|
|
(dwFlags & DIDFT_POV)) {
|
|
int pov[4] = { 0, 0, 0, 0 };
|
|
int axes = 0;
|
|
int povs = 0;
|
|
|
|
for (i = 0; i < This->axes; i++) {
|
|
int wine_obj = This->axis_map[i];
|
|
BOOL skip = FALSE;
|
|
|
|
switch (wine_obj) {
|
|
case 0:
|
|
ddoi.guidType = GUID_XAxis;
|
|
break;
|
|
case 1:
|
|
ddoi.guidType = GUID_YAxis;
|
|
break;
|
|
case 2:
|
|
ddoi.guidType = GUID_ZAxis;
|
|
break;
|
|
case 3:
|
|
ddoi.guidType = GUID_RxAxis;
|
|
break;
|
|
case 4:
|
|
ddoi.guidType = GUID_RyAxis;
|
|
break;
|
|
case 5:
|
|
ddoi.guidType = GUID_RzAxis;
|
|
break;
|
|
case 6:
|
|
ddoi.guidType = GUID_Slider;
|
|
break;
|
|
case 7:
|
|
ddoi.guidType = GUID_Slider;
|
|
break;
|
|
case 8:
|
|
pov[0]++;
|
|
ddoi.guidType = GUID_POV;
|
|
break;
|
|
case 9:
|
|
pov[1]++;
|
|
ddoi.guidType = GUID_POV;
|
|
break;
|
|
case 10:
|
|
pov[2]++;
|
|
ddoi.guidType = GUID_POV;
|
|
break;
|
|
case 11:
|
|
pov[3]++;
|
|
ddoi.guidType = GUID_POV;
|
|
break;
|
|
default:
|
|
ddoi.guidType = GUID_Unknown;
|
|
}
|
|
if (wine_obj < 8) {
|
|
user_offset = This->offsets[wine_obj]; /* get user offset from wine index */
|
|
user_object = offset_to_object(This, user_offset);
|
|
|
|
ddoi.dwType = This->user_df->rgodf[user_object].dwType & 0x00ffffff;
|
|
ddoi.dwOfs = This->user_df->rgodf[user_object].dwOfs;
|
|
sprintf(ddoi.tszName, "Axis %d", axes);
|
|
axes++;
|
|
} else {
|
|
if (pov[wine_obj - 8] < 2) {
|
|
user_offset = This->offsets[wine_obj]; /* get user offset from wine index */
|
|
user_object = offset_to_object(This, user_offset);
|
|
|
|
ddoi.dwType = This->user_df->rgodf[user_object].dwType & 0x00ffffff;
|
|
ddoi.dwOfs = This->user_df->rgodf[user_object].dwOfs;
|
|
sprintf(ddoi.tszName, "POV %d", povs);
|
|
povs++;
|
|
} else
|
|
skip = TRUE;
|
|
}
|
|
if (!skip) {
|
|
_dump_OBJECTINSTANCEA(&ddoi);
|
|
if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE)
|
|
return DI_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((dwFlags == DIDFT_ALL) ||
|
|
(dwFlags & DIDFT_BUTTON)) {
|
|
|
|
/* The DInput SDK says that GUID_Button is only for mouse buttons but well... */
|
|
ddoi.guidType = GUID_Button;
|
|
|
|
for (i = 0; i < This->buttons; i++) {
|
|
user_offset = This->offsets[i + 12]; /* get user offset from wine index */
|
|
user_object = offset_to_object(This, user_offset);
|
|
ddoi.guidType = GUID_Button;
|
|
ddoi.dwType = This->user_df->rgodf[user_object].dwType & 0x00ffffff;
|
|
ddoi.dwOfs = This->user_df->rgodf[user_object].dwOfs;
|
|
sprintf(ddoi.tszName, "Button %d", i);
|
|
_dump_OBJECTINSTANCEA(&ddoi);
|
|
if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
|
|
}
|
|
}
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* EnumObjects : enumerate the different buttons and axis...
|
|
*/
|
|
static HRESULT WINAPI JoystickWImpl_EnumObjects(
|
|
LPDIRECTINPUTDEVICE8W iface,
|
|
LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
|
|
LPVOID lpvRef,
|
|
DWORD dwFlags)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
device_enumobjects_AtoWcb_data data;
|
|
|
|
data.lpCallBack = lpCallback;
|
|
data.lpvRef = lpvRef;
|
|
|
|
return JoystickAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetProperty : get input device properties
|
|
*/
|
|
static HRESULT WINAPI JoystickAImpl_GetProperty(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
REFGUID rguid,
|
|
LPDIPROPHEADER pdiph)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p,%s,%p)\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;
|
|
int obj = find_property(This, pdiph);
|
|
/* The app is querying the current range of the axis
|
|
* return the lMin and lMax values */
|
|
if (obj >= 0) {
|
|
pr->lMin = This->props[obj].lMin;
|
|
pr->lMax = This->props[obj].lMax;
|
|
TRACE("range(%ld, %ld) obj=%d\n", pr->lMin, pr->lMax, obj);
|
|
return DI_OK;
|
|
}
|
|
break;
|
|
}
|
|
case (DWORD) DIPROP_DEADZONE: {
|
|
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
|
|
int obj = find_property(This, pdiph);
|
|
if (obj >= 0) {
|
|
pd->dwData = This->props[obj].lDeadZone;
|
|
TRACE("deadzone(%ld) obj=%d\n", pd->dwData, obj);
|
|
return DI_OK;
|
|
}
|
|
break;
|
|
}
|
|
case (DWORD) DIPROP_SATURATION: {
|
|
LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
|
|
int obj = find_property(This, pdiph);
|
|
if (obj >= 0) {
|
|
pd->dwData = This->props[obj].lSaturation;
|
|
TRACE("saturation(%ld) obj=%d\n", pd->dwData, obj);
|
|
return DI_OK;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
|
|
break;
|
|
}
|
|
}
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetObjectInfo : get object info
|
|
*/
|
|
HRESULT WINAPI JoystickAImpl_GetObjectInfo(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
LPDIDEVICEOBJECTINSTANCEA pdidoi,
|
|
DWORD dwObj,
|
|
DWORD dwHow)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
DIDEVICEOBJECTINSTANCEA didoiA;
|
|
unsigned int i;
|
|
|
|
TRACE("(%p,%p,%ld,0x%08lx(%s))\n",
|
|
iface, pdidoi, dwObj, dwHow,
|
|
dwHow == DIPH_BYOFFSET ? "DIPH_BYOFFSET" :
|
|
dwHow == DIPH_BYID ? "DIPH_BYID" :
|
|
dwHow == DIPH_BYUSAGE ? "DIPH_BYUSAGE" :
|
|
"UNKNOWN");
|
|
|
|
if (pdidoi == NULL) {
|
|
WARN("invalid parameter: pdidoi = NULL\n");
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ((pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA)) &&
|
|
(pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A))) {
|
|
WARN("invalid parameter: pdidoi->dwSize = %ld != %d or %d\n",
|
|
pdidoi->dwSize, sizeof(DIDEVICEOBJECTINSTANCEA),
|
|
sizeof(DIDEVICEOBJECTINSTANCE_DX3A));
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
ZeroMemory(&didoiA, sizeof(didoiA));
|
|
didoiA.dwSize = pdidoi->dwSize;
|
|
|
|
switch (dwHow) {
|
|
case DIPH_BYOFFSET: {
|
|
int axis = 0;
|
|
int pov = 0;
|
|
int button = 0;
|
|
for (i = 0; i < This->user_df->dwNumObjs; i++) {
|
|
if (This->user_df->rgodf[i].dwOfs == dwObj) {
|
|
if (This->user_df->rgodf[i].pguid)
|
|
didoiA.guidType = *This->user_df->rgodf[i].pguid;
|
|
else
|
|
didoiA.guidType = GUID_NULL;
|
|
|
|
didoiA.dwOfs = dwObj;
|
|
didoiA.dwType = This->user_df->rgodf[i].dwType;
|
|
didoiA.dwFlags = This->user_df->rgodf[i].dwFlags;
|
|
|
|
if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_AXIS)
|
|
sprintf(didoiA.tszName, "Axis %d", axis);
|
|
else if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_POV)
|
|
sprintf(didoiA.tszName, "POV %d", pov);
|
|
else if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_BUTTON)
|
|
sprintf(didoiA.tszName, "Button %d", button);
|
|
|
|
CopyMemory(pdidoi, &didoiA, pdidoi->dwSize);
|
|
return DI_OK;
|
|
}
|
|
|
|
if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_AXIS)
|
|
axis++;
|
|
else if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_POV)
|
|
pov++;
|
|
else if (DIDFT_GETTYPE(This->user_df->rgodf[i].dwType) & DIDFT_BUTTON)
|
|
button++;
|
|
}
|
|
break;
|
|
}
|
|
case DIPH_BYID:
|
|
FIXME("dwHow = DIPH_BYID not implemented\n");
|
|
break;
|
|
case DIPH_BYUSAGE:
|
|
FIXME("dwHow = DIPH_BYUSAGE not implemented\n");
|
|
break;
|
|
default:
|
|
WARN("invalid parameter: dwHow = %08lx\n", dwHow);
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
CopyMemory(pdidoi, &didoiA, pdidoi->dwSize);
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetDeviceInfo : get information about a device's identity
|
|
*/
|
|
HRESULT WINAPI JoystickAImpl_GetDeviceInfo(
|
|
LPDIRECTINPUTDEVICE8A iface,
|
|
LPDIDEVICEINSTANCEA pdidi)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p,%p)\n", iface, pdidi);
|
|
|
|
if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
|
|
(pdidi->dwSize != sizeof(DIDEVICEINSTANCEA))) {
|
|
WARN("invalid parameter: pdidi->dwSize = %ld != %d or %d\n",
|
|
pdidi->dwSize, sizeof(DIDEVICEINSTANCE_DX3A),
|
|
sizeof(DIDEVICEINSTANCEA));
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* Return joystick */
|
|
pdidi->guidInstance = GUID_Joystick;
|
|
pdidi->guidProduct = DInput_Wine_Joystick_GUID;
|
|
/* we only support traditional joysticks for now */
|
|
if (This->dinput->version >= 8)
|
|
pdidi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
|
else
|
|
pdidi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
|
strcpy(pdidi->tszInstanceName, "Joystick");
|
|
strcpy(pdidi->tszProductName, This->name);
|
|
if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) {
|
|
pdidi->guidFFDriver = GUID_NULL;
|
|
pdidi->wUsagePage = 0;
|
|
pdidi->wUsage = 0;
|
|
}
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* GetDeviceInfo : get information about a device's identity
|
|
*/
|
|
HRESULT WINAPI JoystickWImpl_GetDeviceInfo(
|
|
LPDIRECTINPUTDEVICE8W iface,
|
|
LPDIDEVICEINSTANCEW pdidi)
|
|
{
|
|
JoystickImpl *This = (JoystickImpl *)iface;
|
|
|
|
TRACE("(%p,%p)\n", iface, pdidi);
|
|
|
|
if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
|
|
(pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) {
|
|
WARN("invalid parameter: pdidi->dwSize = %ld != %d or %d\n",
|
|
pdidi->dwSize, sizeof(DIDEVICEINSTANCE_DX3W),
|
|
sizeof(DIDEVICEINSTANCEW));
|
|
return DIERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* Return joystick */
|
|
pdidi->guidInstance = GUID_Joystick;
|
|
pdidi->guidProduct = DInput_Wine_Joystick_GUID;
|
|
/* we only support traditional joysticks for now */
|
|
if (This->dinput->version >= 8)
|
|
pdidi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
|
else
|
|
pdidi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
|
MultiByteToWideChar(CP_ACP, 0, "Joystick", -1, pdidi->tszInstanceName, MAX_PATH);
|
|
MultiByteToWideChar(CP_ACP, 0, This->name, -1, pdidi->tszProductName, MAX_PATH);
|
|
if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3W)) {
|
|
pdidi->guidFFDriver = GUID_NULL;
|
|
pdidi->wUsagePage = 0;
|
|
pdidi->wUsage = 0;
|
|
}
|
|
|
|
return DI_OK;
|
|
}
|
|
|
|
static IDirectInputDevice8AVtbl JoystickAvt =
|
|
{
|
|
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,
|
|
JoystickAImpl_GetObjectInfo,
|
|
JoystickAImpl_GetDeviceInfo,
|
|
IDirectInputDevice2AImpl_RunControlPanel,
|
|
IDirectInputDevice2AImpl_Initialize,
|
|
IDirectInputDevice2AImpl_CreateEffect,
|
|
IDirectInputDevice2AImpl_EnumEffects,
|
|
IDirectInputDevice2AImpl_GetEffectInfo,
|
|
IDirectInputDevice2AImpl_GetForceFeedbackState,
|
|
IDirectInputDevice2AImpl_SendForceFeedbackCommand,
|
|
IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
|
|
IDirectInputDevice2AImpl_Escape,
|
|
JoystickAImpl_Poll,
|
|
IDirectInputDevice2AImpl_SendDeviceData,
|
|
IDirectInputDevice7AImpl_EnumEffectsInFile,
|
|
IDirectInputDevice7AImpl_WriteEffectToFile,
|
|
IDirectInputDevice8AImpl_BuildActionMap,
|
|
IDirectInputDevice8AImpl_SetActionMap,
|
|
IDirectInputDevice8AImpl_GetImageInfo
|
|
};
|
|
|
|
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
|
|
# define XCAST(fun) (typeof(SysJoystickWvt.fun))
|
|
#else
|
|
# define XCAST(fun) (void*)
|
|
#endif
|
|
|
|
static IDirectInputDevice8WVtbl SysJoystickWvt =
|
|
{
|
|
IDirectInputDevice2WImpl_QueryInterface,
|
|
XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
|
|
XCAST(Release)JoystickAImpl_Release,
|
|
XCAST(GetCapabilities)JoystickAImpl_GetCapabilities,
|
|
JoystickWImpl_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,
|
|
IDirectInputDevice2WImpl_GetObjectInfo,
|
|
JoystickWImpl_GetDeviceInfo,
|
|
XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
|
|
XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
|
|
XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
|
|
IDirectInputDevice2WImpl_EnumEffects,
|
|
IDirectInputDevice2WImpl_GetEffectInfo,
|
|
XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
|
|
XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
|
|
XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
|
|
XCAST(Escape)IDirectInputDevice2AImpl_Escape,
|
|
XCAST(Poll)JoystickAImpl_Poll,
|
|
XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
|
|
IDirectInputDevice7WImpl_EnumEffectsInFile,
|
|
IDirectInputDevice7WImpl_WriteEffectToFile,
|
|
IDirectInputDevice8WImpl_BuildActionMap,
|
|
IDirectInputDevice8WImpl_SetActionMap,
|
|
IDirectInputDevice8WImpl_GetImageInfo
|
|
};
|
|
#undef XCAST
|
|
|
|
#endif /* HAVE_LINUX_22_JOYSTICK_API */
|