winejoystick: Separate Linux-specific code into a separate file.
This commit is contained in:
parent
24fc876e61
commit
01227ab267
|
@ -2,4 +2,5 @@ MODULE = winejoystick.drv
|
|||
IMPORTS = winmm user32
|
||||
|
||||
C_SRCS = \
|
||||
joystick.c
|
||||
joystick.c \
|
||||
joystick_linux.c
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* joystick functions
|
||||
* WinMM joystick driver common code
|
||||
*
|
||||
* Copyright 1997 Andreas Mohr
|
||||
* Copyright 2000 Wolfgang Schwotzer
|
||||
|
@ -18,506 +18,35 @@
|
|||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* - nearly all joystick functions can be regarded as obsolete,
|
||||
* as Linux (2.1.x) now supports extended joysticks with a completely
|
||||
* new joystick driver interface
|
||||
* New driver's documentation says:
|
||||
* "For backward compatibility the old interface is still included,
|
||||
* but will be dropped in the future."
|
||||
* Thus we should implement the new interface and at most keep the old
|
||||
* routines for backward compatibility.
|
||||
* - better support of enhanced joysticks (Linux 2.2 interface is available)
|
||||
* - support more joystick drivers (like the XInput extension)
|
||||
* - should load joystick DLL as any other driver (instead of hardcoding)
|
||||
* the driver's name, and load it as any low lever driver.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_IOCTL_H
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_JOYSTICK_H
|
||||
#include <linux/joystick.h>
|
||||
#ifdef SW_MAX
|
||||
#undef SW_MAX
|
||||
#endif
|
||||
#define JOYDEV_NEW "/dev/input/js%d"
|
||||
#define JOYDEV_OLD "/dev/js%d"
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "winuser.h"
|
||||
#include "winnls.h"
|
||||
#include "mmddk.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(joystick);
|
||||
|
||||
#define MAXJOYSTICK (JOYSTICKID2 + 30)
|
||||
|
||||
typedef struct tagWINE_JSTCK {
|
||||
int joyIntf;
|
||||
BOOL in_use;
|
||||
/* Some extra info we need to make this actually work under the
|
||||
Linux 2.2 event api.
|
||||
First of all, we cannot keep closing and reopening the device file -
|
||||
that blows away the state of the stick device, and we lose events. So, we
|
||||
need to open the low-level device once, and close it when we are done.
|
||||
|
||||
Secondly, the event API only gives us what's changed. However, Windows apps
|
||||
want the whole state every time, so we have to cache the data.
|
||||
*/
|
||||
|
||||
int dev; /* Linux level device file descriptor */
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int r;
|
||||
int u;
|
||||
int v;
|
||||
int pov_x;
|
||||
int pov_y;
|
||||
int buttons;
|
||||
char axesMap[ABS_MAX + 1];
|
||||
} WINE_JSTCK;
|
||||
|
||||
static WINE_JSTCK JSTCK_Data[MAXJOYSTICK];
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_drvGet [internal]
|
||||
*/
|
||||
static WINE_JSTCK *JSTCK_drvGet(DWORD_PTR dwDevID)
|
||||
{
|
||||
int p;
|
||||
|
||||
if ((dwDevID - (DWORD_PTR)JSTCK_Data) % sizeof(JSTCK_Data[0]) != 0)
|
||||
return NULL;
|
||||
p = (dwDevID - (DWORD_PTR)JSTCK_Data) / sizeof(JSTCK_Data[0]);
|
||||
if (p < 0 || p >= MAXJOYSTICK || !((WINE_JSTCK*)dwDevID)->in_use)
|
||||
return NULL;
|
||||
|
||||
return (WINE_JSTCK*)dwDevID;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_drvOpen [internal]
|
||||
*/
|
||||
static LRESULT JSTCK_drvOpen(LPSTR str, DWORD dwIntf)
|
||||
{
|
||||
if (dwIntf >= MAXJOYSTICK || JSTCK_Data[dwIntf].in_use)
|
||||
return 0;
|
||||
|
||||
JSTCK_Data[dwIntf].joyIntf = dwIntf;
|
||||
JSTCK_Data[dwIntf].in_use = TRUE;
|
||||
return (LRESULT)&JSTCK_Data[dwIntf];
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_drvClose [internal]
|
||||
*/
|
||||
static LRESULT JSTCK_drvClose(DWORD_PTR dwDevID)
|
||||
{
|
||||
WINE_JSTCK* jstck = JSTCK_drvGet(dwDevID);
|
||||
|
||||
if (jstck == NULL)
|
||||
return 0;
|
||||
jstck->in_use = FALSE;
|
||||
if (jstck->dev > 0)
|
||||
{
|
||||
close(jstck->dev);
|
||||
jstck->dev = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct js_status
|
||||
{
|
||||
int buttons;
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_OpenDevice [internal]
|
||||
*/
|
||||
static int JSTCK_OpenDevice(WINE_JSTCK* jstick)
|
||||
{
|
||||
char buf[20];
|
||||
int flags;
|
||||
|
||||
if (jstick->dev > 0)
|
||||
return jstick->dev;
|
||||
|
||||
sprintf(buf, JOYDEV_NEW, jstick->joyIntf);
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
flags = O_RDONLY | O_NONBLOCK;
|
||||
#else
|
||||
flags = O_RDONLY;
|
||||
#endif
|
||||
if ((jstick->dev = open(buf, flags)) < 0) {
|
||||
sprintf(buf, JOYDEV_OLD, jstick->joyIntf);
|
||||
if ((jstick->dev = open(buf, flags)) < 0)
|
||||
return jstick->dev;
|
||||
}
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
ioctl(jstick->dev, JSIOCGAXMAP, jstick->axesMap);
|
||||
#endif
|
||||
return jstick->dev;
|
||||
}
|
||||
#include "joystick.h"
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* JoyGetDevCaps [MMSYSTEM.102]
|
||||
* DriverProc (JOYSTICK.@)
|
||||
*/
|
||||
static LRESULT JSTCK_GetDevCaps(DWORD_PTR dwDevID, LPJOYCAPSW lpCaps, DWORD dwSize)
|
||||
LRESULT CALLBACK JSTCK_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
|
||||
{
|
||||
WINE_JSTCK* jstck;
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
int dev;
|
||||
char nrOfAxes;
|
||||
char nrOfButtons;
|
||||
char identString[MAXPNAMELEN];
|
||||
int i;
|
||||
int driverVersion;
|
||||
#else
|
||||
static const WCHAR ini[] = {'W','i','n','e',' ','J','o','y','s','t','i','c','k',' ','D','r','i','v','e','r',0};
|
||||
#endif
|
||||
|
||||
if ((jstck = JSTCK_drvGet(dwDevID)) == NULL)
|
||||
return MMSYSERR_NODRIVER;
|
||||
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS;
|
||||
ioctl(dev, JSIOCGAXES, &nrOfAxes);
|
||||
ioctl(dev, JSIOCGBUTTONS, &nrOfButtons);
|
||||
ioctl(dev, JSIOCGVERSION, &driverVersion);
|
||||
ioctl(dev, JSIOCGNAME(sizeof(identString)), identString);
|
||||
TRACE("Driver: 0x%06x, Name: %s, #Axes: %d, #Buttons: %d\n",
|
||||
driverVersion, identString, nrOfAxes, nrOfButtons);
|
||||
lpCaps->wMid = MM_MICROSOFT;
|
||||
lpCaps->wPid = MM_PC_JOYSTICK;
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, identString, -1, lpCaps->szPname, MAXPNAMELEN);
|
||||
lpCaps->szPname[MAXPNAMELEN-1] = '\0';
|
||||
lpCaps->wXmin = 0;
|
||||
lpCaps->wXmax = 0xFFFF;
|
||||
lpCaps->wYmin = 0;
|
||||
lpCaps->wYmax = 0xFFFF;
|
||||
lpCaps->wZmin = 0;
|
||||
lpCaps->wZmax = (nrOfAxes >= 3) ? 0xFFFF : 0;
|
||||
#ifdef BODGE_THE_HAT
|
||||
/* Half-Life won't allow you to map an axis event to things like
|
||||
"next weapon" and "use". Linux reports the hat on my stick as
|
||||
axis U and V. So, IFF BODGE_THE_HAT is defined, lie through our
|
||||
teeth and say we have 32 buttons, and we will map the axes to
|
||||
the high buttons. Really, perhaps this should be a registry entry,
|
||||
or even a parameter to the Linux joystick driver (which would completely
|
||||
remove the need for this.)
|
||||
*/
|
||||
lpCaps->wNumButtons = 32;
|
||||
#else
|
||||
lpCaps->wNumButtons = nrOfButtons;
|
||||
#endif
|
||||
if (dwSize == sizeof(JOYCAPSW)) {
|
||||
/* complete 95 structure */
|
||||
lpCaps->wRmin = 0;
|
||||
lpCaps->wRmax = 0xFFFF;
|
||||
lpCaps->wUmin = 0;
|
||||
lpCaps->wUmax = 0xFFFF;
|
||||
lpCaps->wVmin = 0;
|
||||
lpCaps->wVmax = 0xFFFF;
|
||||
lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */
|
||||
lpCaps->wNumAxes = 0; /* nr of axes in use */
|
||||
lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */
|
||||
lpCaps->szRegKey[0] = 0;
|
||||
lpCaps->szOEMVxD[0] = 0;
|
||||
lpCaps->wCaps = 0;
|
||||
for (i = 0; i < nrOfAxes; i++) {
|
||||
switch (jstck->axesMap[i]) {
|
||||
case 0: /* X */
|
||||
case 1: /* Y */
|
||||
lpCaps->wNumAxes++;
|
||||
break;
|
||||
case 2: /* Z */
|
||||
case 6: /* Throttle */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASZ;
|
||||
break;
|
||||
case 5: /* Rz */
|
||||
case 7: /* Rudder */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASR;
|
||||
break;
|
||||
case 3: /* Rx */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASU;
|
||||
break;
|
||||
case 4: /* Ry */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASV;
|
||||
break;
|
||||
case 16: /* Hat 0 X */
|
||||
case 17: /* Hat 0 Y */
|
||||
lpCaps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR;
|
||||
/* TODO: JOYCAPS_POVCTS handling */
|
||||
break;
|
||||
default:
|
||||
WARN("Unknown axis %hhu(%u). Skipped.\n", jstck->axesMap[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
lpCaps->wMid = MM_MICROSOFT;
|
||||
lpCaps->wPid = MM_PC_JOYSTICK;
|
||||
strcpyW(lpCaps->szPname, ini); /* joystick product name */
|
||||
lpCaps->wXmin = 0;
|
||||
lpCaps->wXmax = 0xFFFF;
|
||||
lpCaps->wYmin = 0;
|
||||
lpCaps->wYmax = 0xFFFF;
|
||||
lpCaps->wZmin = 0;
|
||||
lpCaps->wZmax = 0;
|
||||
lpCaps->wNumButtons = 2;
|
||||
if (dwSize == sizeof(JOYCAPSW)) {
|
||||
/* complete 95 structure */
|
||||
lpCaps->wRmin = 0;
|
||||
lpCaps->wRmax = 0;
|
||||
lpCaps->wUmin = 0;
|
||||
lpCaps->wUmax = 0;
|
||||
lpCaps->wVmin = 0;
|
||||
lpCaps->wVmax = 0;
|
||||
lpCaps->wCaps = 0;
|
||||
lpCaps->wMaxAxes = 2;
|
||||
lpCaps->wNumAxes = 2;
|
||||
lpCaps->wMaxButtons = 4;
|
||||
lpCaps->szRegKey[0] = 0;
|
||||
lpCaps->szOEMVxD[0] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_GetPos [internal]
|
||||
*/
|
||||
static LRESULT JSTCK_GetPosEx(DWORD_PTR dwDevID, LPJOYINFOEX lpInfo)
|
||||
{
|
||||
WINE_JSTCK* jstck;
|
||||
int dev;
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
struct js_event ev;
|
||||
#else
|
||||
struct js_status js;
|
||||
int dev_stat;
|
||||
#endif
|
||||
|
||||
if ((jstck = JSTCK_drvGet(dwDevID)) == NULL)
|
||||
return MMSYSERR_NODRIVER;
|
||||
|
||||
if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS;
|
||||
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
while ((read(dev, &ev, sizeof(struct js_event))) > 0) {
|
||||
if (ev.type == (JS_EVENT_AXIS)) {
|
||||
switch (jstck->axesMap[ev.number]) {
|
||||
case 0: /* X */
|
||||
jstck->x = ev.value;
|
||||
break;
|
||||
case 1: /* Y */
|
||||
jstck->y = ev.value;
|
||||
break;
|
||||
case 2: /* Z */
|
||||
case 6: /* Throttle */
|
||||
jstck->z = ev.value;
|
||||
break;
|
||||
case 5: /* Rz */
|
||||
case 7: /* Rudder */
|
||||
jstck->r = ev.value;
|
||||
break;
|
||||
case 3: /* Rx */
|
||||
jstck->u = ev.value;
|
||||
break;
|
||||
case 4: /* Ry */
|
||||
jstck->v = ev.value;
|
||||
break;
|
||||
case 16: /* Hat 0 X */
|
||||
jstck->pov_x = ev.value;
|
||||
break;
|
||||
case 17: /* Hat 0 Y */
|
||||
jstck->pov_y = ev.value;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown joystick event '%d'\n", ev.number);
|
||||
}
|
||||
} else if (ev.type == (JS_EVENT_BUTTON)) {
|
||||
if (ev.value) {
|
||||
jstck->buttons |= (1 << ev.number);
|
||||
/* FIXME: what to do for this field when
|
||||
* multiple buttons are depressed ?
|
||||
*/
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtonNumber = ev.number + 1;
|
||||
}
|
||||
else
|
||||
jstck->buttons &= ~(1 << ev.number);
|
||||
}
|
||||
}
|
||||
/* EAGAIN is returned when the queue is empty */
|
||||
if (errno != EAGAIN) {
|
||||
/* FIXME: error should not be ignored */
|
||||
ERR("Error while reading joystick state (%s)\n", strerror(errno));
|
||||
}
|
||||
/* Now, copy the cached values into Window's structure... */
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtons = jstck->buttons;
|
||||
if (lpInfo->dwFlags & JOY_RETURNX)
|
||||
lpInfo->dwXpos = jstck->x + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNY)
|
||||
lpInfo->dwYpos = jstck->y + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNZ)
|
||||
lpInfo->dwZpos = jstck->z + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNR)
|
||||
lpInfo->dwRpos = jstck->r + 32767;
|
||||
# ifdef BODGE_THE_HAT
|
||||
else if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
{
|
||||
if (jstck->r > 0)
|
||||
lpInfo->dwButtons |= 1<<7;
|
||||
else if (jstck->r < 0)
|
||||
lpInfo->dwButtons |= 1<<8;
|
||||
}
|
||||
# endif
|
||||
if (lpInfo->dwFlags & JOY_RETURNU)
|
||||
lpInfo->dwUpos = jstck->u + 32767;
|
||||
# ifdef BODGE_THE_HAT
|
||||
else if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
{
|
||||
if (jstck->u > 0)
|
||||
lpInfo->dwButtons |= 1<<9;
|
||||
else if (jstck->u < 0)
|
||||
lpInfo->dwButtons |= 1<<10;
|
||||
}
|
||||
# endif
|
||||
if (lpInfo->dwFlags & JOY_RETURNV)
|
||||
lpInfo->dwVpos = jstck->v + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNPOV) {
|
||||
if (jstck->pov_y > 0) {
|
||||
if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 22500; /* SW */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 13500; /* SE */
|
||||
else
|
||||
lpInfo->dwPOV = 18000; /* S, JOY_POVBACKWARD */
|
||||
} else if (jstck->pov_y < 0) {
|
||||
if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 31500; /* NW */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 4500; /* NE */
|
||||
else
|
||||
lpInfo->dwPOV = 0; /* N, JOY_POVFORWARD */
|
||||
} else if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 27000; /* W, JOY_POVLEFT */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 9000; /* E, JOY_POVRIGHT */
|
||||
else
|
||||
lpInfo->dwPOV = JOY_POVCENTERED; /* Center */
|
||||
}
|
||||
|
||||
#else
|
||||
dev_stat = read(dev, &js, sizeof(js));
|
||||
if (dev_stat != sizeof(js)) {
|
||||
return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
|
||||
}
|
||||
js.x = js.x<<8;
|
||||
js.y = js.y<<8;
|
||||
if (lpInfo->dwFlags & JOY_RETURNX)
|
||||
lpInfo->dwXpos = js.x; /* FIXME: perhaps multiply it somehow ? */
|
||||
if (lpInfo->dwFlags & JOY_RETURNY)
|
||||
lpInfo->dwYpos = js.y;
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtons = js.buttons;
|
||||
#endif
|
||||
|
||||
TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, flags: 0x%04x (fd %d)\n",
|
||||
lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos,
|
||||
lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos,
|
||||
lpInfo->dwButtons, lpInfo->dwFlags, dev
|
||||
);
|
||||
|
||||
return JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_GetPos [internal]
|
||||
*/
|
||||
static LRESULT JSTCK_GetPos(DWORD_PTR dwDevID, LPJOYINFO lpInfo)
|
||||
{
|
||||
JOYINFOEX ji;
|
||||
LONG ret;
|
||||
|
||||
memset(&ji, 0, sizeof(ji));
|
||||
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS;
|
||||
ret = JSTCK_GetPosEx(dwDevID, &ji);
|
||||
if (ret == JOYERR_NOERROR) {
|
||||
lpInfo->wXpos = ji.dwXpos;
|
||||
lpInfo->wYpos = ji.dwYpos;
|
||||
lpInfo->wZpos = ji.dwZpos;
|
||||
lpInfo->wButtons = ji.dwButtons;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* DriverProc (JOYSTICK.@)
|
||||
*/
|
||||
LRESULT CALLBACK JSTCK_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
|
||||
LPARAM dwParam1, LPARAM dwParam2)
|
||||
{
|
||||
/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
|
||||
/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
|
||||
|
||||
switch(wMsg) {
|
||||
case DRV_LOAD: return 1;
|
||||
case DRV_FREE: return 1;
|
||||
case DRV_OPEN: return JSTCK_drvOpen((LPSTR)dwParam1, dwParam2);
|
||||
case DRV_CLOSE: return JSTCK_drvClose(dwDevID);
|
||||
case DRV_ENABLE: return 1;
|
||||
case DRV_DISABLE: return 1;
|
||||
case DRV_QUERYCONFIGURE: return 1;
|
||||
case DRV_CONFIGURE: MessageBoxA(0, "JoyStick MultiMedia Driver !", "JoyStick Driver", MB_OK); return 1;
|
||||
case DRV_INSTALL: return DRVCNF_RESTART;
|
||||
case DRV_REMOVE: return DRVCNF_RESTART;
|
||||
case DRV_LOAD: return 1;
|
||||
case DRV_FREE: return 1;
|
||||
case DRV_OPEN: return driver_open((LPSTR)dwParam1, dwParam2);
|
||||
case DRV_CLOSE: return driver_close(dwDevID);
|
||||
case DRV_ENABLE: return 1;
|
||||
case DRV_DISABLE: return 1;
|
||||
case DRV_QUERYCONFIGURE: return 1;
|
||||
case DRV_CONFIGURE: MessageBoxA(0, "JoyStick MultiMedia Driver !", "JoyStick Driver", MB_OK); return 1;
|
||||
case DRV_INSTALL: return DRVCNF_RESTART;
|
||||
case DRV_REMOVE: return DRVCNF_RESTART;
|
||||
|
||||
case JDD_GETNUMDEVS: return 1;
|
||||
case JDD_GETDEVCAPS: return JSTCK_GetDevCaps(dwDevID, (LPJOYCAPSW)dwParam1, dwParam2);
|
||||
case JDD_GETPOS: return JSTCK_GetPos(dwDevID, (LPJOYINFO)dwParam1);
|
||||
case JDD_GETNUMDEVS: return 1;
|
||||
case JDD_GETDEVCAPS: return driver_joyGetDevCaps(dwDevID, (LPJOYCAPSW)dwParam1, dwParam2);
|
||||
case JDD_GETPOS: return driver_joyGetPos(dwDevID, (LPJOYINFO)dwParam1);
|
||||
case JDD_SETCALIBRATION:
|
||||
case JDD_CONFIGCHANGED: return JOYERR_NOCANDO;
|
||||
case JDD_GETPOSEX: return JSTCK_GetPosEx(dwDevID, (LPJOYINFOEX)dwParam1);
|
||||
case JDD_CONFIGCHANGED: return JOYERR_NOCANDO;
|
||||
case JDD_GETPOSEX: return driver_joyGetPosEx(dwDevID, (LPJOYINFOEX)dwParam1);
|
||||
default:
|
||||
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
|
||||
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* WinMM joystick driver header
|
||||
*
|
||||
* Copyright 2015 Ken Thomases for CodeWeavers 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "mmddk.h"
|
||||
#include "winuser.h"
|
||||
|
||||
|
||||
LRESULT driver_open(LPSTR str, DWORD index) DECLSPEC_HIDDEN;
|
||||
LRESULT driver_close(DWORD_PTR device_id) DECLSPEC_HIDDEN;
|
||||
LRESULT driver_joyGetDevCaps(DWORD_PTR device_id, JOYCAPSW* caps, DWORD size) DECLSPEC_HIDDEN;
|
||||
LRESULT driver_joyGetPosEx(DWORD_PTR device_id, JOYINFOEX* info) DECLSPEC_HIDDEN;
|
||||
LRESULT driver_joyGetPos(DWORD_PTR device_id, JOYINFO* info) DECLSPEC_HIDDEN;
|
|
@ -0,0 +1,490 @@
|
|||
/*
|
||||
* joystick functions
|
||||
*
|
||||
* Copyright 1997 Andreas Mohr
|
||||
* Copyright 2000 Wolfgang Schwotzer
|
||||
* Copyright 2002 David Hagood
|
||||
*
|
||||
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
* - nearly all joystick functions can be regarded as obsolete,
|
||||
* as Linux (2.1.x) now supports extended joysticks with a completely
|
||||
* new joystick driver interface
|
||||
* New driver's documentation says:
|
||||
* "For backward compatibility the old interface is still included,
|
||||
* but will be dropped in the future."
|
||||
* Thus we should implement the new interface and at most keep the old
|
||||
* routines for backward compatibility.
|
||||
* - better support of enhanced joysticks (Linux 2.2 interface is available)
|
||||
* - support more joystick drivers (like the XInput extension)
|
||||
* - should load joystick DLL as any other driver (instead of hardcoding)
|
||||
* the driver's name, and load it as any low lever driver.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#ifdef HAVE_LINUX_JOYSTICK_H
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_IOCTL_H
|
||||
#include <linux/ioctl.h>
|
||||
#endif
|
||||
#include <linux/joystick.h>
|
||||
#ifdef SW_MAX
|
||||
#undef SW_MAX
|
||||
#endif
|
||||
#define JOYDEV_NEW "/dev/input/js%d"
|
||||
#define JOYDEV_OLD "/dev/js%d"
|
||||
#include <errno.h>
|
||||
|
||||
#include "joystick.h"
|
||||
|
||||
#include "wingdi.h"
|
||||
#include "winnls.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(joystick);
|
||||
|
||||
#define MAXJOYSTICK (JOYSTICKID2 + 30)
|
||||
|
||||
typedef struct tagWINE_JSTCK {
|
||||
int joyIntf;
|
||||
BOOL in_use;
|
||||
/* Some extra info we need to make this actually work under the
|
||||
Linux 2.2 event api.
|
||||
First of all, we cannot keep closing and reopening the device file -
|
||||
that blows away the state of the stick device, and we lose events. So, we
|
||||
need to open the low-level device once, and close it when we are done.
|
||||
|
||||
Secondly, the event API only gives us what's changed. However, Windows apps
|
||||
want the whole state every time, so we have to cache the data.
|
||||
*/
|
||||
|
||||
int dev; /* Linux level device file descriptor */
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int r;
|
||||
int u;
|
||||
int v;
|
||||
int pov_x;
|
||||
int pov_y;
|
||||
int buttons;
|
||||
char axesMap[ABS_MAX + 1];
|
||||
} WINE_JSTCK;
|
||||
|
||||
static WINE_JSTCK JSTCK_Data[MAXJOYSTICK];
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_drvGet [internal]
|
||||
*/
|
||||
static WINE_JSTCK *JSTCK_drvGet(DWORD_PTR dwDevID)
|
||||
{
|
||||
int p;
|
||||
|
||||
if ((dwDevID - (DWORD_PTR)JSTCK_Data) % sizeof(JSTCK_Data[0]) != 0)
|
||||
return NULL;
|
||||
p = (dwDevID - (DWORD_PTR)JSTCK_Data) / sizeof(JSTCK_Data[0]);
|
||||
if (p < 0 || p >= MAXJOYSTICK || !((WINE_JSTCK*)dwDevID)->in_use)
|
||||
return NULL;
|
||||
|
||||
return (WINE_JSTCK*)dwDevID;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* driver_open
|
||||
*/
|
||||
LRESULT driver_open(LPSTR str, DWORD dwIntf)
|
||||
{
|
||||
if (dwIntf >= MAXJOYSTICK || JSTCK_Data[dwIntf].in_use)
|
||||
return 0;
|
||||
|
||||
JSTCK_Data[dwIntf].joyIntf = dwIntf;
|
||||
JSTCK_Data[dwIntf].in_use = TRUE;
|
||||
return (LRESULT)&JSTCK_Data[dwIntf];
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* driver_close
|
||||
*/
|
||||
LRESULT driver_close(DWORD_PTR dwDevID)
|
||||
{
|
||||
WINE_JSTCK* jstck = JSTCK_drvGet(dwDevID);
|
||||
|
||||
if (jstck == NULL)
|
||||
return 0;
|
||||
jstck->in_use = FALSE;
|
||||
if (jstck->dev > 0)
|
||||
{
|
||||
close(jstck->dev);
|
||||
jstck->dev = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct js_status
|
||||
{
|
||||
int buttons;
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* JSTCK_OpenDevice [internal]
|
||||
*/
|
||||
static int JSTCK_OpenDevice(WINE_JSTCK* jstick)
|
||||
{
|
||||
char buf[20];
|
||||
int flags;
|
||||
|
||||
if (jstick->dev > 0)
|
||||
return jstick->dev;
|
||||
|
||||
sprintf(buf, JOYDEV_NEW, jstick->joyIntf);
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
flags = O_RDONLY | O_NONBLOCK;
|
||||
#else
|
||||
flags = O_RDONLY;
|
||||
#endif
|
||||
if ((jstick->dev = open(buf, flags)) < 0) {
|
||||
sprintf(buf, JOYDEV_OLD, jstick->joyIntf);
|
||||
if ((jstick->dev = open(buf, flags)) < 0)
|
||||
return jstick->dev;
|
||||
}
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
ioctl(jstick->dev, JSIOCGAXMAP, jstick->axesMap);
|
||||
#endif
|
||||
return jstick->dev;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* JoyGetDevCaps [MMSYSTEM.102]
|
||||
*/
|
||||
LRESULT driver_joyGetDevCaps(DWORD_PTR dwDevID, LPJOYCAPSW lpCaps, DWORD dwSize)
|
||||
{
|
||||
WINE_JSTCK* jstck;
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
int dev;
|
||||
char nrOfAxes;
|
||||
char nrOfButtons;
|
||||
char identString[MAXPNAMELEN];
|
||||
int i;
|
||||
int driverVersion;
|
||||
#else
|
||||
static const WCHAR ini[] = {'W','i','n','e',' ','J','o','y','s','t','i','c','k',' ','D','r','i','v','e','r',0};
|
||||
#endif
|
||||
|
||||
if ((jstck = JSTCK_drvGet(dwDevID)) == NULL)
|
||||
return MMSYSERR_NODRIVER;
|
||||
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS;
|
||||
ioctl(dev, JSIOCGAXES, &nrOfAxes);
|
||||
ioctl(dev, JSIOCGBUTTONS, &nrOfButtons);
|
||||
ioctl(dev, JSIOCGVERSION, &driverVersion);
|
||||
ioctl(dev, JSIOCGNAME(sizeof(identString)), identString);
|
||||
TRACE("Driver: 0x%06x, Name: %s, #Axes: %d, #Buttons: %d\n",
|
||||
driverVersion, identString, nrOfAxes, nrOfButtons);
|
||||
lpCaps->wMid = MM_MICROSOFT;
|
||||
lpCaps->wPid = MM_PC_JOYSTICK;
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, identString, -1, lpCaps->szPname, MAXPNAMELEN);
|
||||
lpCaps->szPname[MAXPNAMELEN-1] = '\0';
|
||||
lpCaps->wXmin = 0;
|
||||
lpCaps->wXmax = 0xFFFF;
|
||||
lpCaps->wYmin = 0;
|
||||
lpCaps->wYmax = 0xFFFF;
|
||||
lpCaps->wZmin = 0;
|
||||
lpCaps->wZmax = (nrOfAxes >= 3) ? 0xFFFF : 0;
|
||||
#ifdef BODGE_THE_HAT
|
||||
/* Half-Life won't allow you to map an axis event to things like
|
||||
"next weapon" and "use". Linux reports the hat on my stick as
|
||||
axis U and V. So, IFF BODGE_THE_HAT is defined, lie through our
|
||||
teeth and say we have 32 buttons, and we will map the axes to
|
||||
the high buttons. Really, perhaps this should be a registry entry,
|
||||
or even a parameter to the Linux joystick driver (which would completely
|
||||
remove the need for this.)
|
||||
*/
|
||||
lpCaps->wNumButtons = 32;
|
||||
#else
|
||||
lpCaps->wNumButtons = nrOfButtons;
|
||||
#endif
|
||||
if (dwSize == sizeof(JOYCAPSW)) {
|
||||
/* complete 95 structure */
|
||||
lpCaps->wRmin = 0;
|
||||
lpCaps->wRmax = 0xFFFF;
|
||||
lpCaps->wUmin = 0;
|
||||
lpCaps->wUmax = 0xFFFF;
|
||||
lpCaps->wVmin = 0;
|
||||
lpCaps->wVmax = 0xFFFF;
|
||||
lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */
|
||||
lpCaps->wNumAxes = 0; /* nr of axes in use */
|
||||
lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */
|
||||
lpCaps->szRegKey[0] = 0;
|
||||
lpCaps->szOEMVxD[0] = 0;
|
||||
lpCaps->wCaps = 0;
|
||||
for (i = 0; i < nrOfAxes; i++) {
|
||||
switch (jstck->axesMap[i]) {
|
||||
case 0: /* X */
|
||||
case 1: /* Y */
|
||||
lpCaps->wNumAxes++;
|
||||
break;
|
||||
case 2: /* Z */
|
||||
case 6: /* Throttle */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASZ;
|
||||
break;
|
||||
case 5: /* Rz */
|
||||
case 7: /* Rudder */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASR;
|
||||
break;
|
||||
case 3: /* Rx */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASU;
|
||||
break;
|
||||
case 4: /* Ry */
|
||||
lpCaps->wNumAxes++;
|
||||
lpCaps->wCaps |= JOYCAPS_HASV;
|
||||
break;
|
||||
case 16: /* Hat 0 X */
|
||||
case 17: /* Hat 0 Y */
|
||||
lpCaps->wCaps |= JOYCAPS_HASPOV | JOYCAPS_POV4DIR;
|
||||
/* TODO: JOYCAPS_POVCTS handling */
|
||||
break;
|
||||
default:
|
||||
WARN("Unknown axis %hhu(%u). Skipped.\n", jstck->axesMap[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
lpCaps->wMid = MM_MICROSOFT;
|
||||
lpCaps->wPid = MM_PC_JOYSTICK;
|
||||
strcpyW(lpCaps->szPname, ini); /* joystick product name */
|
||||
lpCaps->wXmin = 0;
|
||||
lpCaps->wXmax = 0xFFFF;
|
||||
lpCaps->wYmin = 0;
|
||||
lpCaps->wYmax = 0xFFFF;
|
||||
lpCaps->wZmin = 0;
|
||||
lpCaps->wZmax = 0;
|
||||
lpCaps->wNumButtons = 2;
|
||||
if (dwSize == sizeof(JOYCAPSW)) {
|
||||
/* complete 95 structure */
|
||||
lpCaps->wRmin = 0;
|
||||
lpCaps->wRmax = 0;
|
||||
lpCaps->wUmin = 0;
|
||||
lpCaps->wUmax = 0;
|
||||
lpCaps->wVmin = 0;
|
||||
lpCaps->wVmax = 0;
|
||||
lpCaps->wCaps = 0;
|
||||
lpCaps->wMaxAxes = 2;
|
||||
lpCaps->wNumAxes = 2;
|
||||
lpCaps->wMaxButtons = 4;
|
||||
lpCaps->szRegKey[0] = 0;
|
||||
lpCaps->szOEMVxD[0] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* driver_joyGetPos
|
||||
*/
|
||||
LRESULT driver_joyGetPosEx(DWORD_PTR dwDevID, LPJOYINFOEX lpInfo)
|
||||
{
|
||||
WINE_JSTCK* jstck;
|
||||
int dev;
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
struct js_event ev;
|
||||
#else
|
||||
struct js_status js;
|
||||
int dev_stat;
|
||||
#endif
|
||||
|
||||
if ((jstck = JSTCK_drvGet(dwDevID)) == NULL)
|
||||
return MMSYSERR_NODRIVER;
|
||||
|
||||
if ((dev = JSTCK_OpenDevice(jstck)) < 0) return JOYERR_PARMS;
|
||||
|
||||
#ifdef HAVE_LINUX_22_JOYSTICK_API
|
||||
while ((read(dev, &ev, sizeof(struct js_event))) > 0) {
|
||||
if (ev.type == (JS_EVENT_AXIS)) {
|
||||
switch (jstck->axesMap[ev.number]) {
|
||||
case 0: /* X */
|
||||
jstck->x = ev.value;
|
||||
break;
|
||||
case 1: /* Y */
|
||||
jstck->y = ev.value;
|
||||
break;
|
||||
case 2: /* Z */
|
||||
case 6: /* Throttle */
|
||||
jstck->z = ev.value;
|
||||
break;
|
||||
case 5: /* Rz */
|
||||
case 7: /* Rudder */
|
||||
jstck->r = ev.value;
|
||||
break;
|
||||
case 3: /* Rx */
|
||||
jstck->u = ev.value;
|
||||
break;
|
||||
case 4: /* Ry */
|
||||
jstck->v = ev.value;
|
||||
break;
|
||||
case 16: /* Hat 0 X */
|
||||
jstck->pov_x = ev.value;
|
||||
break;
|
||||
case 17: /* Hat 0 Y */
|
||||
jstck->pov_y = ev.value;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown joystick event '%d'\n", ev.number);
|
||||
}
|
||||
} else if (ev.type == (JS_EVENT_BUTTON)) {
|
||||
if (ev.value) {
|
||||
jstck->buttons |= (1 << ev.number);
|
||||
/* FIXME: what to do for this field when
|
||||
* multiple buttons are depressed ?
|
||||
*/
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtonNumber = ev.number + 1;
|
||||
}
|
||||
else
|
||||
jstck->buttons &= ~(1 << ev.number);
|
||||
}
|
||||
}
|
||||
/* EAGAIN is returned when the queue is empty */
|
||||
if (errno != EAGAIN) {
|
||||
/* FIXME: error should not be ignored */
|
||||
ERR("Error while reading joystick state (%s)\n", strerror(errno));
|
||||
}
|
||||
/* Now, copy the cached values into Window's structure... */
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtons = jstck->buttons;
|
||||
if (lpInfo->dwFlags & JOY_RETURNX)
|
||||
lpInfo->dwXpos = jstck->x + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNY)
|
||||
lpInfo->dwYpos = jstck->y + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNZ)
|
||||
lpInfo->dwZpos = jstck->z + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNR)
|
||||
lpInfo->dwRpos = jstck->r + 32767;
|
||||
# ifdef BODGE_THE_HAT
|
||||
else if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
{
|
||||
if (jstck->r > 0)
|
||||
lpInfo->dwButtons |= 1<<7;
|
||||
else if (jstck->r < 0)
|
||||
lpInfo->dwButtons |= 1<<8;
|
||||
}
|
||||
# endif
|
||||
if (lpInfo->dwFlags & JOY_RETURNU)
|
||||
lpInfo->dwUpos = jstck->u + 32767;
|
||||
# ifdef BODGE_THE_HAT
|
||||
else if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
{
|
||||
if (jstck->u > 0)
|
||||
lpInfo->dwButtons |= 1<<9;
|
||||
else if (jstck->u < 0)
|
||||
lpInfo->dwButtons |= 1<<10;
|
||||
}
|
||||
# endif
|
||||
if (lpInfo->dwFlags & JOY_RETURNV)
|
||||
lpInfo->dwVpos = jstck->v + 32767;
|
||||
if (lpInfo->dwFlags & JOY_RETURNPOV) {
|
||||
if (jstck->pov_y > 0) {
|
||||
if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 22500; /* SW */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 13500; /* SE */
|
||||
else
|
||||
lpInfo->dwPOV = 18000; /* S, JOY_POVBACKWARD */
|
||||
} else if (jstck->pov_y < 0) {
|
||||
if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 31500; /* NW */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 4500; /* NE */
|
||||
else
|
||||
lpInfo->dwPOV = 0; /* N, JOY_POVFORWARD */
|
||||
} else if (jstck->pov_x < 0)
|
||||
lpInfo->dwPOV = 27000; /* W, JOY_POVLEFT */
|
||||
else if (jstck->pov_x > 0)
|
||||
lpInfo->dwPOV = 9000; /* E, JOY_POVRIGHT */
|
||||
else
|
||||
lpInfo->dwPOV = JOY_POVCENTERED; /* Center */
|
||||
}
|
||||
|
||||
#else
|
||||
dev_stat = read(dev, &js, sizeof(js));
|
||||
if (dev_stat != sizeof(js)) {
|
||||
return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */
|
||||
}
|
||||
js.x = js.x<<8;
|
||||
js.y = js.y<<8;
|
||||
if (lpInfo->dwFlags & JOY_RETURNX)
|
||||
lpInfo->dwXpos = js.x; /* FIXME: perhaps multiply it somehow ? */
|
||||
if (lpInfo->dwFlags & JOY_RETURNY)
|
||||
lpInfo->dwYpos = js.y;
|
||||
if (lpInfo->dwFlags & JOY_RETURNBUTTONS)
|
||||
lpInfo->dwButtons = js.buttons;
|
||||
#endif
|
||||
|
||||
TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, flags: 0x%04x (fd %d)\n",
|
||||
lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos,
|
||||
lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos,
|
||||
lpInfo->dwButtons, lpInfo->dwFlags, dev
|
||||
);
|
||||
|
||||
return JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* driver_joyGetPos
|
||||
*/
|
||||
LRESULT driver_joyGetPos(DWORD_PTR dwDevID, LPJOYINFO lpInfo)
|
||||
{
|
||||
JOYINFOEX ji;
|
||||
LONG ret;
|
||||
|
||||
memset(&ji, 0, sizeof(ji));
|
||||
|
||||
ji.dwSize = sizeof(ji);
|
||||
ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNBUTTONS;
|
||||
ret = driver_joyGetPosEx(dwDevID, &ji);
|
||||
if (ret == JOYERR_NOERROR) {
|
||||
lpInfo->wXpos = ji.dwXpos;
|
||||
lpInfo->wYpos = ji.dwYpos;
|
||||
lpInfo->wZpos = ji.dwZpos;
|
||||
lpInfo->wButtons = ji.dwButtons;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LINUX_JOYSTICK_H */
|
Loading…
Reference in New Issue