From 2a3b0a1daddb8f776501b17bfc267a5beacf4742 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Sat, 26 Feb 2000 13:14:04 +0000 Subject: [PATCH] Moved hardware related handling to dlls/winmm/joystick driver. Got rid of joySendMessages() hack (now implementation with a timer). --- Make.rules.in | 1 + configure | 2 + configure.in | 1 + dlls/Makefile.in | 5 + dlls/winmm/Makefile.in | 1 + dlls/winmm/joystick.c | 741 ++++++++++-------------------- dlls/winmm/joystick/.cvsignore | 3 + dlls/winmm/joystick/Makefile.in | 23 + dlls/winmm/joystick/joystick.c | 370 +++++++++++++++ dlls/winmm/joystick/joystick.spec | 5 + include/debugdefs.h | 4 +- include/message.h | 2 - include/mmddk.h | 144 +++++- windows/message.c | 3 - 14 files changed, 797 insertions(+), 508 deletions(-) create mode 100644 dlls/winmm/joystick/.cvsignore create mode 100644 dlls/winmm/joystick/Makefile.in create mode 100644 dlls/winmm/joystick/joystick.c create mode 100644 dlls/winmm/joystick/joystick.spec diff --git a/Make.rules.in b/Make.rules.in index 3f760f73d9b..e2ecbdfcc6f 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -93,6 +93,7 @@ DLLS = \ icmp \ imagehlp \ imm32 \ + joystick.drv \ lz32 \ mcianim.drv \ mciavi.drv \ diff --git a/configure b/configure index 3baf0a2d22f..9413897affd 100755 --- a/configure +++ b/configure @@ -6215,6 +6215,7 @@ dlls/winaspi/Makefile dlls/windebug/Makefile dlls/wing/Makefile dlls/winmm/Makefile +dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile @@ -6427,6 +6428,7 @@ dlls/winaspi/Makefile dlls/windebug/Makefile dlls/wing/Makefile dlls/winmm/Makefile +dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile diff --git a/configure.in b/configure.in index 429d0ef9a67..3f1c70daf67 100644 --- a/configure.in +++ b/configure.in @@ -977,6 +977,7 @@ dlls/winaspi/Makefile dlls/windebug/Makefile dlls/wing/Makefile dlls/winmm/Makefile +dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile diff --git a/dlls/Makefile.in b/dlls/Makefile.in index 00b51b72646..3c689040140 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -37,6 +37,7 @@ DLLFILES = \ win87em/libwin87em.@LIBEXT@ \ windebug/libwindebug.@LIBEXT@ \ wing/libwing.@LIBEXT@ \ + winmm/joystick/libjoystick.drv.@LIBEXT@ \ winmm/mcianim/libmcianim.drv.@LIBEXT@ \ winmm/mciavi/libmciavi.drv.@LIBEXT@ \ winmm/mcicda/libmcicda.drv.@LIBEXT@ \ @@ -93,6 +94,10 @@ libimm32.@LIBEXT@: imm32/libimm32.@LIBEXT@ $(RM) $@ $(LN_S) imm32/libimm32.@LIBEXT@ $@ +libjoystick.drv.@LIBEXT@: winmm/joystick/libjoystick.drv.@LIBEXT@ + $(RM) $@ + $(LN_S) winmm/joystick/libjoystick.drv.@LIBEXT@ $@ + liblz32.@LIBEXT@: lzexpand/liblz32.@LIBEXT@ $(RM) $@ $(LN_S) lzexpand/liblz32.@LIBEXT@ $@ diff --git a/dlls/winmm/Makefile.in b/dlls/winmm/Makefile.in index 9fc2ca80c27..a02e07612b3 100644 --- a/dlls/winmm/Makefile.in +++ b/dlls/winmm/Makefile.in @@ -28,6 +28,7 @@ RC_SRCS= \ all: check_wrc $ $(MODULE).o SUBDIRS = \ + joystick \ mcianim \ mciavi \ mcicda \ diff --git a/dlls/winmm/joystick.c b/dlls/winmm/joystick.c index e773639f0b4..22d20936513 100644 --- a/dlls/winmm/joystick.c +++ b/dlls/winmm/joystick.c @@ -1,23 +1,10 @@ +/* -*- tab-width: 8; c-basic-offset: 4 -*- */ /* * joystick functions * * Copyright 1997 Andreas Mohr - * - * 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 docu 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. - */ - -/* - * Wolfgang Schwotzer - * - * 01/2000 added support for new joystick driver - * + * 2000 Wolfgang Schwotzer + * Eric Pouech */ #include "config.h" @@ -28,18 +15,11 @@ #include #include #include -#ifdef HAVE_LINUX_JOYSTICK_H -#include -#define JOYDEV "/dev/js%d" -#endif -#ifdef HAVE_SYS_ERRNO_H -#include -#endif -#include "windef.h" +#include "winbase.h" #include "wingdi.h" #include "winuser.h" -#include "winbase.h" -#include "mmsystem.h" +#include "driver.h" +#include "winemm.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(mmsys); @@ -48,178 +28,79 @@ DEFAULT_DEBUG_CHANNEL(mmsys); #define JOY_PERIOD_MIN (10) /* min Capture time period */ #define JOY_PERIOD_MAX (1000) /* max Capture time period */ -static int count_use[MAXJOYSTICK] = {0, 0}; -static int joy_nr_open = 0; -static BOOL16 joyCaptured = FALSE; -static HWND16 CaptureWnd[MAXJOYSTICK] = {0, 0}; -static int joy_dev[MAXJOYSTICK] = {-1, -1}; -static JOYINFO16 joyCapData[MAXJOYSTICK]; -static unsigned int joy_threshold[MAXJOYSTICK] = {0, 0}; - -struct js_status -{ - int buttons; - int x; - int y; -}; +typedef struct tagWINE_JOYSTICK { + JOYINFO ji; + HWND hCapture; + UINT wTimer; + DWORD threshold; + BOOL bChanged; +} WINE_JOYSTICK; +static WINE_JOYSTICK JOY_Sticks[MAXJOYSTICK]; +static HDRVR JOY_Driver; /************************************************************************** - * joyOpenDriver [internal] + * JOY_LoadDriver [internal] */ -BOOL16 joyOpenDriver(WORD wID) +static BOOL JOY_LoadDriver(void) { - char buf[20]; - int flags; + if (JOY_Driver) + return TRUE; - if (wID>=MAXJOYSTICK) return FALSE; - if (joy_dev[wID] >= 0) return TRUE; /* was already open */ -#ifdef HAVE_LINUX_JOYSTICK_H - sprintf(buf,JOYDEV,wID); - flags = O_RDONLY; -#ifdef HAVE_LINUX_22_JOYSTICK_API - flags |= O_NONBLOCK; -#endif - if ((joy_dev[wID] = open(buf, flags)) >= 0) { - joy_nr_open++; - return TRUE; - } else - return FALSE; -#else - return FALSE; -#endif /* HAVE_LINUX_JOYSTICK_H */ + return JOY_Driver = OpenDriverA("joystick.drv", 0, 0); } /************************************************************************** - * joyCloseDriver [internal] + * JOY_Timer [internal] */ -void joyCloseDriver(WORD wID) +static void CALLBACK JOY_Timer(HWND hWnd, UINT wMsg, UINT wTimer, DWORD dwTime) { - if (joy_dev[wID] >= 0) { - close(joy_dev[wID]); - joy_dev[wID] = -1; - joy_nr_open--; + int i; + WINE_JOYSTICK* joy; + JOYINFO ji; + LONG pos; + unsigned buttonChange; + + for (i = 0; i < MAXJOYSTICK; i++) { + joy = &JOY_Sticks[i]; + + if (joy->hCapture != hWnd) continue; + + joyGetPos(i, &ji); + pos = MAKELONG(ji.wXpos, ji.wYpos); + + if (!joy->bChanged || + abs(joy->ji.wXpos - ji.wXpos) > joy->threshold || + abs(joy->ji.wYpos - ji.wYpos) > joy->threshold) { + SendMessageA(joy->hCapture, MM_JOY1MOVE + i, ji.wButtons, pos); + joy->ji.wXpos = ji.wXpos; + joy->ji.wYpos = ji.wYpos; } -} - -/************************************************************************** - * joyUpdateCaptureData [internal] - */ -#ifdef HAVE_LINUX_22_JOYSTICK_API -void joyUpdateCaptureData(WORD wID) -{ - struct js_event ev; - unsigned int ButtonState; - int messageType = 0; - - if (joyOpenDriver(wID) == FALSE) return; - while (read(joy_dev[wID], &ev, sizeof(struct js_event)) > 0) { - if (ev.type & JS_EVENT_AXIS) { - if (ev.number == 0) - joyCapData[wID].wXpos = ev.value + 32767; - if (ev.number == 1) - joyCapData[wID].wYpos = ev.value + 32767; - if (ev.number <= 1) /* Message for X, Y-Axis */ - SendMessageA(CaptureWnd[wID], MM_JOY1MOVE + wID, - joyCapData[wID].wButtons, - MAKELONG(joyCapData[wID].wXpos, - joyCapData[wID].wYpos)); - if (ev.number == 2) { /* Message for Z-axis */ - joyCapData[wID].wZpos = ev.value + 32767; - SendMessageA(CaptureWnd[wID], MM_JOY1ZMOVE + wID, - joyCapData[wID].wButtons, - joyCapData[wID].wZpos); - } - } else if (ev.type & JS_EVENT_BUTTON) { - if (ev.value) { - joyCapData[wID].wButtons |= (1 << ev.number); - messageType = MM_JOY1BUTTONDOWN; - } else { - joyCapData[wID].wButtons &= ~(1 << ev.number); - messageType = MM_JOY1BUTTONUP; - } - /* create button state with changed buttons and - pressed buttons */ - ButtonState = ((1 << (ev.number + 8)) & 0xFF00) | - (joyCapData[wID].wButtons & 0xFF); - SendMessageA(CaptureWnd[wID], messageType + wID, - ButtonState, - MAKELONG(joyCapData[wID].wXpos, - joyCapData[wID].wYpos)); - } + if (!joy->bChanged || + abs(joy->ji.wZpos - ji.wZpos) > joy->threshold) { + SendMessageA(joy->hCapture, MM_JOY1ZMOVE + i, ji.wButtons, pos); + joy->ji.wZpos = ji.wZpos; } - /* EAGAIN is returned when the queue is empty */ - if (errno != EAGAIN) { - /* FIXME: error should not be ignored */ + if ((buttonChange = joy->ji.wButtons ^ ji.wButtons) != 0) { + if (ji.wButtons & buttonChange) + SendMessageA(joy->hCapture, MM_JOY1BUTTONDOWN + i, + (buttonChange << 8) | (ji.wButtons & buttonChange), pos); + if (joy->ji.wButtons & buttonChange) + SendMessageA(joy->hCapture, MM_JOY1BUTTONUP + i, + (buttonChange << 8) | (joy->ji.wButtons & buttonChange), pos); + joy->ji.wButtons = ji.wButtons; } -} -#endif - -/************************************************************************** - * joySendMessages [internal] - */ -void joySendMessages(void) -{ - int joy; -#ifndef HAVE_LINUX_22_JOYSTICK_API - struct js_status js; -#endif - if (joy_nr_open) - { - for (joy=0; joy < MAXJOYSTICK; joy++) - if (joy_dev[joy] >= 0) { - if (count_use[joy] > 250) { - joyCloseDriver(joy); - count_use[joy] = 0; - } - count_use[joy]++; - } else - return; - } - if (joyCaptured == FALSE) return; - - TRACE(" --\n"); - -#ifdef HAVE_LINUX_22_JOYSTICK_API - for (joy=0; joy < MAXJOYSTICK; joy++) - joyUpdateCaptureData(joy); - return; -#else - for (joy=0; joy < MAXJOYSTICK; joy++) { - int dev_stat; - - if (joyOpenDriver(joy) == FALSE) continue; - dev_stat = read(joy_dev[joy], &js, sizeof(js)); - if (dev_stat == sizeof(js)) { - js.x = js.x<<8; - js.y = js.y<<8; - if ((joyCapData[joy].wXpos != js.x) || (joyCapData[joy].wYpos != js.y)) { - SendMessageA(CaptureWnd[joy], MM_JOY1MOVE + joy, js.buttons, MAKELONG(js.x, js.y)); - joyCapData[joy].wXpos = js.x; - joyCapData[joy].wYpos = js.y; - } - if (joyCapData[joy].wButtons != js.buttons) { - unsigned int ButtonChanged = (WORD)(joyCapData[joy].wButtons ^ js.buttons)<<8; - if (joyCapData[joy].wButtons < js.buttons) - SendMessageA(CaptureWnd[joy], MM_JOY1BUTTONDOWN + joy, ButtonChanged, MAKELONG(js.x, js.y)); - else - if (joyCapData[joy].wButtons > js.buttons) - SendMessageA(CaptureWnd[joy], MM_JOY1BUTTONUP -+ joy, ButtonChanged, MAKELONG(js.x, js.y)); - joyCapData[joy].wButtons = js.buttons; - } - } - } -#endif + } } - /************************************************************************** - * JoyGetNumDevs [MMSYSTEM.101] + * JoyGetNumDevs [WINMM.30] */ UINT WINAPI joyGetNumDevs(void) { - return joyGetNumDevs16(); + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; + + return SendDriverMessage(JOY_Driver, JDD_GETNUMDEVS, 0L, 0L); } /************************************************************************** @@ -227,307 +108,152 @@ UINT WINAPI joyGetNumDevs(void) */ UINT16 WINAPI joyGetNumDevs16(void) { -/* int joy; - UINT16 joy_cnt = 0; - - for (joy=0; joy= 2.1.45 to be " - "able to use joysticks.\n"); - return joy_cnt;*/ - -/* simply return the max. nr. of supported joysticks. The rest - will be done with joyGetPos or joyGetDevCaps. Look at - MS Joystick Driver */ - - return MAXJOYSTICK; + return joyGetNumDevs(); } /************************************************************************** * JoyGetDevCaps [WINMM.27] */ -MMRESULT WINAPI joyGetDevCapsA(UINT wID, LPJOYCAPSA lpCaps,UINT wSize) +MMRESULT WINAPI joyGetDevCapsA(UINT wID, LPJOYCAPSA lpCaps, UINT wSize) { - JOYCAPS16 jc16; - MMRESULT16 ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16)); + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; - if (ret != JOYERR_NOERROR) return ret; - lpCaps->wMid = jc16.wMid; - lpCaps->wPid = jc16.wPid; - strcpy(lpCaps->szPname,jc16.szPname); - lpCaps->wXmin = jc16.wXmin; - lpCaps->wXmax = jc16.wXmax; - lpCaps->wYmin = jc16.wYmin; - lpCaps->wYmax = jc16.wYmax; - lpCaps->wZmin = jc16.wZmin; - lpCaps->wZmax = jc16.wZmax; - lpCaps->wNumButtons = jc16.wNumButtons; - lpCaps->wPeriodMin = jc16.wPeriodMin; - lpCaps->wPeriodMax = jc16.wPeriodMax; + lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ + lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver) */ - lpCaps->wRmin = jc16.wRmin; - lpCaps->wRmax = jc16.wRmax; - lpCaps->wUmin = jc16.wUmin; - lpCaps->wUmax = jc16.wUmax; - lpCaps->wVmin = jc16.wVmin; - lpCaps->wVmax = jc16.wVmax; - lpCaps->wCaps = jc16.wCaps; - lpCaps->wMaxAxes = jc16.wMaxAxes; - lpCaps->wNumAxes = jc16.wNumAxes; - lpCaps->wMaxButtons = jc16.wMaxButtons; - strcpy(lpCaps->szRegKey,jc16.szRegKey); - strcpy(lpCaps->szOEMVxD,jc16.szOEMVxD); - return ret; -} + return SendDriverMessage(JOY_Driver, JDD_GETDEVCAPS, (DWORD)lpCaps, wSize); +} /************************************************************************** * JoyGetDevCaps [WINMM.28] */ -MMRESULT WINAPI joyGetDevCapsW(UINT wID, LPJOYCAPSW lpCaps,UINT wSize) +MMRESULT WINAPI joyGetDevCapsW(UINT wID, LPJOYCAPSW lpCaps, UINT wSize) { - JOYCAPS16 jc16; - MMRESULT16 ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16)); - - if (ret != JOYERR_NOERROR) return ret; - lpCaps->wMid = jc16.wMid; - lpCaps->wPid = jc16.wPid; - lstrcpyAtoW(lpCaps->szPname,jc16.szPname); - lpCaps->wXmin = jc16.wXmin; - lpCaps->wXmax = jc16.wXmax; - lpCaps->wYmin = jc16.wYmin; - lpCaps->wYmax = jc16.wYmax; - lpCaps->wZmin = jc16.wZmin; - lpCaps->wZmax = jc16.wZmax; - lpCaps->wNumButtons = jc16.wNumButtons; - lpCaps->wPeriodMin = jc16.wPeriodMin; - lpCaps->wPeriodMax = jc16.wPeriodMax; - - lpCaps->wRmin = jc16.wRmin; - lpCaps->wRmax = jc16.wRmax; - lpCaps->wUmin = jc16.wUmin; - lpCaps->wUmax = jc16.wUmax; - lpCaps->wVmin = jc16.wVmin; - lpCaps->wVmax = jc16.wVmax; - lpCaps->wCaps = jc16.wCaps; - lpCaps->wMaxAxes = jc16.wMaxAxes; - lpCaps->wNumAxes = jc16.wNumAxes; - lpCaps->wMaxButtons = jc16.wMaxButtons; - lstrcpyAtoW(lpCaps->szRegKey,jc16.szRegKey); - lstrcpyAtoW(lpCaps->szOEMVxD,jc16.szOEMVxD); - return ret; + JOYCAPSA jca; + MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca)); + + if (ret != JOYERR_NOERROR) return ret; + lpCaps->wMid = jca.wMid; + lpCaps->wPid = jca.wPid; + lstrcpyAtoW(lpCaps->szPname, jca.szPname); + lpCaps->wXmin = jca.wXmin; + lpCaps->wXmax = jca.wXmax; + lpCaps->wYmin = jca.wYmin; + lpCaps->wYmax = jca.wYmax; + lpCaps->wZmin = jca.wZmin; + lpCaps->wZmax = jca.wZmax; + lpCaps->wNumButtons = jca.wNumButtons; + lpCaps->wPeriodMin = jca.wPeriodMin; + lpCaps->wPeriodMax = jca.wPeriodMax; + + if (wSize >= sizeof(JOYCAPSW)) { /* Win95 extensions ? */ + lpCaps->wRmin = jca.wRmin; + lpCaps->wRmax = jca.wRmax; + lpCaps->wUmin = jca.wUmin; + lpCaps->wUmax = jca.wUmax; + lpCaps->wVmin = jca.wVmin; + lpCaps->wVmax = jca.wVmax; + lpCaps->wCaps = jca.wCaps; + lpCaps->wMaxAxes = jca.wMaxAxes; + lpCaps->wNumAxes = jca.wNumAxes; + lpCaps->wMaxButtons = jca.wMaxButtons; + lstrcpyAtoW(lpCaps->szRegKey, jca.szRegKey); + lstrcpyAtoW(lpCaps->szOEMVxD, jca.szOEMVxD); + } + + return ret; } + /************************************************************************** * JoyGetDevCaps [MMSYSTEM.102] */ MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize) { - TRACE("(%04X, %p, %d);\n", - wID, lpCaps, wSize); - if (wID >= MAXJOYSTICK) return MMSYSERR_NODRIVER; -#ifdef HAVE_LINUX_22_JOYSTICK_API - if (joyOpenDriver(wID) == TRUE) { - char nrOfAxes; - char nrOfButtons; - char identString[MAXPNAMELEN]; - int driverVersion; - - ioctl(joy_dev[wID], JSIOCGAXES, &nrOfAxes); - ioctl(joy_dev[wID], JSIOCGBUTTONS, &nrOfButtons); - ioctl(joy_dev[wID], JSIOCGVERSION, &driverVersion); - ioctl(joy_dev[wID], 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; - strncpy(lpCaps->szPname, identString, 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; - lpCaps->wNumButtons = nrOfButtons; - lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ - lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME (same as MS Joystick Driver */ - if (wSize == sizeof(JOYCAPS16)) { - /* complete 95 structure */ - lpCaps->wRmin = 0; - lpCaps->wRmax = nrOfAxes >= 4 ? 0xFFFF : 0; - lpCaps->wUmin = 0; - lpCaps->wUmax = nrOfAxes >= 5 ? 0xFFFF : 0; - lpCaps->wVmin = 0; - lpCaps->wVmax = nrOfAxes >= 6 ? 0xFFFF : 0; - lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */ - lpCaps->wNumAxes = nrOfAxes; /* nr of axes in use */ - lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */ - strcpy(lpCaps->szRegKey,""); - strcpy(lpCaps->szOEMVxD,""); - lpCaps->wCaps = 0; - switch(nrOfAxes) { - case 6: lpCaps->wCaps |= JOYCAPS_HASV; - case 5: lpCaps->wCaps |= JOYCAPS_HASU; - case 4: lpCaps->wCaps |= JOYCAPS_HASR; - case 3: lpCaps->wCaps |= JOYCAPS_HASZ; - /* FIXME: don't know how to detect for - JOYCAPS_HASPOV, JOYCAPS_POV4DIR, JOYCAPS_POVCTS */ - } - } - joyCloseDriver(wID); - return JOYERR_NOERROR; - } else - return JOYERR_PARMS; -#else - if (joyOpenDriver(wID) == TRUE) { - lpCaps->wMid = MM_MICROSOFT; - lpCaps->wPid = MM_PC_JOYSTICK; - strcpy(lpCaps->szPname, "WineJoy"); /* joystick product name */ - lpCaps->wXmin = 0; - lpCaps->wXmax = 0xFFFF; - lpCaps->wYmin = 0; - lpCaps->wYmax = 0xFFFF; - lpCaps->wZmin = 0; - lpCaps->wZmax = 0; - lpCaps->wNumButtons = 2; - lpCaps->wPeriodMin = JOY_PERIOD_MIN; /* FIXME */ - lpCaps->wPeriodMax = JOY_PERIOD_MAX; /* FIXME end */ - if (wSize == sizeof(JOYCAPS16)) { - /* 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; - strcpy(lpCaps->szRegKey,""); - strcpy(lpCaps->szOEMVxD,""); - } - joyCloseDriver(wID); - return JOYERR_NOERROR; - } else - return JOYERR_PARMS; -#endif + JOYCAPSA jca; + MMRESULT ret = joyGetDevCapsA(wID, &jca, sizeof(jca)); + + if (ret != JOYERR_NOERROR) return ret; + lpCaps->wMid = jca.wMid; + lpCaps->wPid = jca.wPid; + strcpy(lpCaps->szPname, jca.szPname); + lpCaps->wXmin = jca.wXmin; + lpCaps->wXmax = jca.wXmax; + lpCaps->wYmin = jca.wYmin; + lpCaps->wYmax = jca.wYmax; + lpCaps->wZmin = jca.wZmin; + lpCaps->wZmax = jca.wZmax; + lpCaps->wNumButtons = jca.wNumButtons; + lpCaps->wPeriodMin = jca.wPeriodMin; + lpCaps->wPeriodMax = jca.wPeriodMax; + + if (wSize >= sizeof(JOYCAPS16)) { /* Win95 extensions ? */ + lpCaps->wRmin = jca.wRmin; + lpCaps->wRmax = jca.wRmax; + lpCaps->wUmin = jca.wUmin; + lpCaps->wUmax = jca.wUmax; + lpCaps->wVmin = jca.wVmin; + lpCaps->wVmax = jca.wVmax; + lpCaps->wCaps = jca.wCaps; + lpCaps->wMaxAxes = jca.wMaxAxes; + lpCaps->wNumAxes = jca.wNumAxes; + lpCaps->wMaxButtons = jca.wMaxButtons; + strcpy(lpCaps->szRegKey, jca.szRegKey); + strcpy(lpCaps->szOEMVxD, jca.szOEMVxD); + } + + return ret; } /************************************************************************** - * JoyGetPosEx [WINMM.31] + * JoyGetPosEx [WINMM.32] */ MMRESULT WINAPI joyGetPosEx(UINT wID, LPJOYINFOEX lpInfo) { - return joyGetPosEx16(wID, lpInfo); + TRACE("(%d, %p);\n", wID, lpInfo); + + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; + + lpInfo->dwXpos = 0; + lpInfo->dwYpos = 0; + lpInfo->dwZpos = 0; + lpInfo->dwRpos = 0; + lpInfo->dwUpos = 0; + lpInfo->dwVpos = 0; + lpInfo->dwButtons = 0; + lpInfo->dwButtonNumber = 0; + lpInfo->dwPOV = 0; + lpInfo->dwReserved1 = 0; + lpInfo->dwReserved2 = 0; + + return SendDriverMessage(JOY_Driver, JDD_GETPOSEX, (DWORD)lpInfo, 0L); } /************************************************************************** - * JoyGetPosEx [WINMM.31] + * JoyGetPosEx16 [MMSYSTEM.] */ MMRESULT16 WINAPI joyGetPosEx16(UINT16 wID, LPJOYINFOEX lpInfo) { - - TRACE("(%04X, %p)\n", wID, lpInfo); - - if (wID < MAXJOYSTICK) { -#ifdef HAVE_LINUX_22_JOYSTICK_API - struct js_event ev; - - joyCloseDriver(wID); - if (joyOpenDriver(wID) == FALSE) return JOYERR_PARMS; - lpInfo->dwSize = sizeof(JOYINFOEX); - lpInfo->dwXpos = lpInfo->dwYpos =lpInfo->dwZpos = 0; - lpInfo->dwButtons = lpInfo->dwFlags = 0; - /* After opening the device it's state can be - read with JS_EVENT_INIT flag */ - while ((read(joy_dev[wID], &ev, sizeof(struct js_event))) > 0) { - if (ev.type == (JS_EVENT_AXIS | JS_EVENT_INIT)) { - switch (ev.number) { - case 0: lpInfo->dwXpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNX; break; - case 1: lpInfo->dwYpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNY; break; - case 2: lpInfo->dwZpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNZ; break; - case 3: lpInfo->dwRpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNR; break; - case 4: lpInfo->dwUpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNU; break; - case 5: lpInfo->dwVpos = ev.value + 32767; - lpInfo->dwFlags |= JOY_RETURNV; break; - } - } else if (ev.type == - (JS_EVENT_BUTTON | JS_EVENT_INIT)) { - if (ev.value) - lpInfo->dwButtons |= (1 << ev.number); - else - lpInfo->dwButtons &= ~(1 << ev.number); - lpInfo->dwFlags |= JOY_RETURNBUTTONS; - } - } - /* EAGAIN is returned when the queue is empty */ - if (errno != EAGAIN) { - /* FIXME: error should not be ignored */ - } - joyCloseDriver(wID); - TRACE("x: %ld, y: %ld, z: %ld, r: %ld, u: %ld, v: %ld, \ - buttons: 0x%04x, flags: 0x%04x\n", - lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos, - lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos, - (unsigned int)lpInfo->dwButtons, - (unsigned int)lpInfo->dwFlags); - return JOYERR_NOERROR; -#else - struct js_status js; - int dev_stat; - - if (joyOpenDriver(wID) == FALSE) return JOYERR_UNPLUGGED; - dev_stat = read(joy_dev[wID], &js, sizeof(js)); - if (dev_stat != sizeof(js)) { - joyCloseDriver(wID); - return JOYERR_UNPLUGGED; /* FIXME: perhaps wrong, but what should I return else ? */ - } - count_use[wID] = 0; - js.x = js.x<<8; - js.y = js.y<<8; - lpInfo->dwXpos = js.x; /* FIXME: perhaps multiply it somehow ? */ - lpInfo->dwYpos = js.y; - lpInfo->dwZpos = 0; - lpInfo->dwButtons = js.buttons; - lpInfo->dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNBUTTONS; - TRACE("x: %ld, y: %ld, buttons: 0x%04x, flags: 0x%04x\n", - lpInfo->dwXpos, lpInfo->dwYpos, - (unsigned int)lpInfo->dwButtons, - (unsigned int)lpInfo->dwFlags); - return JOYERR_NOERROR; -#endif - } else - return JOYERR_PARMS; + return joyGetPosEx(wID, lpInfo); } /************************************************************************** - * JoyGetPos [WINMM.30] + * JoyGetPos [WINMM.31] */ MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo) { - JOYINFOEX ji; - MMRESULT ret; + TRACE("(%d, %p);\n", wID, lpInfo); + + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; + + lpInfo->wXpos = 0; + lpInfo->wYpos = 0; + lpInfo->wZpos = 0; + lpInfo->wButtons = 0; - TRACE("(%d, %p);\n", wID, lpInfo); - - ret = joyGetPosEx16(wID,&ji); - lpInfo->wXpos = ji.dwXpos; - lpInfo->wYpos = ji.dwYpos; - lpInfo->wZpos = ji.dwZpos; - lpInfo->wButtons = ji.dwButtons; - return ret; + return SendDriverMessage(JOY_Driver, JDD_GETPOS, (DWORD)lpInfo, 0L); } /************************************************************************** @@ -535,29 +261,31 @@ MMRESULT WINAPI joyGetPos(UINT wID, LPJOYINFO lpInfo) */ MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo) { - JOYINFOEX ji; - MMRESULT16 ret; - - TRACE("(%d, %p);\n", wID, lpInfo); - - ret = joyGetPosEx16(wID,&ji); - lpInfo->wXpos = ji.dwXpos; - lpInfo->wYpos = ji.dwYpos; - lpInfo->wZpos = ji.dwZpos; - lpInfo->wButtons = ji.dwButtons; - return ret; + JOYINFO ji; + MMRESULT ret; + + TRACE("(%d, %p);\n", wID, lpInfo); + + if ((ret = joyGetPos(wID, &ji)) == JOYERR_NOERROR) { + lpInfo->wXpos = ji.wXpos; + lpInfo->wYpos = ji.wYpos; + lpInfo->wZpos = ji.wZpos; + lpInfo->wButtons = ji.wButtons; + } + return ret; } /************************************************************************** - * JoyGetThreshold [WINMM.32] + * JoyGetThreshold [WINMM.36] */ MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold) { - UINT16 thresh; - MMRESULT16 ret = joyGetThreshold16(wID,&thresh); - - *lpThreshold = thresh; - return ret; + TRACE("(%04X, %p);\n", wID, lpThreshold); + + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + + *lpThreshold = JOY_Sticks[wID].threshold; + return JOYERR_NOERROR; } /************************************************************************** @@ -566,17 +294,29 @@ MMRESULT WINAPI joyGetThreshold(UINT wID, LPUINT lpThreshold) MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold) { TRACE("(%04X, %p);\n", wID, lpThreshold); - if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM; - *lpThreshold = joy_threshold[wID]; + + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + + *lpThreshold = JOY_Sticks[wID].threshold; return JOYERR_NOERROR; } /************************************************************************** - * JoyReleaseCapture [WINMM.33] + * JoyReleaseCapture [WINMM.34] */ MMRESULT WINAPI joyReleaseCapture(UINT wID) { - return joyReleaseCapture16(wID); + TRACE("(%04X);\n", wID); + + if (wID >= MAXJOYSTICK) return JOYERR_PARMS; + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; + if (!JOY_Sticks[wID].hCapture) return JOYERR_NOCANDO; + + KillTimer(JOY_Sticks[wID].hCapture, JOY_Sticks[wID].wTimer); + JOY_Sticks[wID].hCapture = 0; + JOY_Sticks[wID].wTimer = 0; + + return JOYERR_NOERROR; } /************************************************************************** @@ -584,64 +324,63 @@ MMRESULT WINAPI joyReleaseCapture(UINT wID) */ MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID) { - TRACE("(%04X);\n", wID); - if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM; - joyCaptured = FALSE; - joyCloseDriver(wID); - joy_dev[wID] = -1; - CaptureWnd[wID] = 0; + return joyReleaseCapture(wID); +} + +/************************************************************************** + * JoySetCapture [WINMM.35] + */ +MMRESULT WINAPI joySetCapture(HWND hWnd, UINT wID, UINT wPeriod, BOOL bChanged) +{ + TRACE("(%04X, %04X, %d, %d);\n", hWnd, wID, wPeriod, bChanged); + + if (wID >= MAXJOYSTICK || hWnd == 0) return JOYERR_PARMS; + if (wPeriodJOY_PERIOD_MAX) return JOYERR_PARMS; + if (!JOY_LoadDriver()) return MMSYSERR_NODRIVER; + + if (JOY_Sticks[wID].hCapture || !IsWindow(hWnd)) + return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ + + if (joyGetPos(wID, &JOY_Sticks[wID].ji) != JOYERR_NOERROR) + return JOYERR_UNPLUGGED; + + if ((JOY_Sticks[wID].wTimer = SetTimer(hWnd, 0, wPeriod, JOY_Timer)) == 0) + return JOYERR_NOCANDO; + + JOY_Sticks[wID].hCapture = hWnd; + JOY_Sticks[wID].bChanged = bChanged; + return JOYERR_NOERROR; } /************************************************************************** * JoySetCapture [MMSYSTEM.106] */ -MMRESULT WINAPI joySetCapture(HWND hWnd,UINT wID,UINT wPeriod,BOOL bChanged) +MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd, UINT16 wID, UINT16 wPeriod, BOOL16 bChanged) { - return joySetCapture16(hWnd,wID,wPeriod,bChanged); + return joySetCapture16(hWnd, wID, wPeriod, bChanged); } /************************************************************************** - * JoySetCapture [MMSYSTEM.106] - */ -MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd,UINT16 wID,UINT16 wPeriod,BOOL16 bChanged) -{ - - TRACE("(%04X, %04X, %d, %d);\n", - hWnd, wID, wPeriod, bChanged); - if (wID >= MAXJOYSTICK) return JOYERR_PARMS; - if (hWnd == 0) return JOYERR_PARMS; - if (wPeriodJOY_PERIOD_MAX) return JOYERR_PARMS; - if (!CaptureWnd[wID]) { - if (joyOpenDriver(wID) == FALSE) return JOYERR_PARMS; - joyCaptured = TRUE; - CaptureWnd[wID] = hWnd; - joyCapData[wID].wXpos = 0; - joyCapData[wID].wYpos = 0; - joyCapData[wID].wZpos = 0; - joyCapData[wID].wButtons = 0; - return JOYERR_NOERROR; - } else - return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ -} - -/************************************************************************** - * JoySetThreshold [WINMM.35] + * JoySetThreshold [WINMM.36] */ MMRESULT WINAPI joySetThreshold(UINT wID, UINT wThreshold) { - return joySetThreshold16(wID,wThreshold); + TRACE("(%04X, %d);\n", wID, wThreshold); + + if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM; + + JOY_Sticks[wID].threshold = wThreshold; + + return JOYERR_NOERROR; } + /************************************************************************** * JoySetThreshold [MMSYSTEM.107] */ MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold) { - TRACE("(%04X, %d);\n", wID, wThreshold); - - if (wID >= MAXJOYSTICK) return MMSYSERR_INVALPARAM; - joy_threshold[wID] = wThreshold; - return JOYERR_NOERROR; + return joySetThreshold16(wID,wThreshold); } /************************************************************************** diff --git a/dlls/winmm/joystick/.cvsignore b/dlls/winmm/joystick/.cvsignore new file mode 100644 index 00000000000..00cf59ecd64 --- /dev/null +++ b/dlls/winmm/joystick/.cvsignore @@ -0,0 +1,3 @@ +*.spec.c +Makefile +libjoystick.drv.so.1.0 diff --git a/dlls/winmm/joystick/Makefile.in b/dlls/winmm/joystick/Makefile.in new file mode 100644 index 00000000000..d21e08f70e3 --- /dev/null +++ b/dlls/winmm/joystick/Makefile.in @@ -0,0 +1,23 @@ +DEFS = @DLLFLAGS@ -D__WINE__ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +LIBEXT = @LIBEXT@ +MODULE = joystick.drv +SOVERSION = 1.0 + +SPEC_SRCS = \ + joystick.spec + +C_SRCS = \ + joystick.c + +all: lib$(MODULE).$(LIBEXT) + +@MAKE_RULES@ + +clean:: + $(RM) lib$(MODULE).$(LIBEXT).$(SOVERSION) + +### Dependencies: diff --git a/dlls/winmm/joystick/joystick.c b/dlls/winmm/joystick/joystick.c new file mode 100644 index 00000000000..e1846fca206 --- /dev/null +++ b/dlls/winmm/joystick/joystick.c @@ -0,0 +1,370 @@ +/* -*- tab-width: 8; c-basic-offset: 4 -*- */ +/* + * joystick functions + * + * Copyright 1997 Andreas Mohr + * + * 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 docu 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. + */ + +/* + * Wolfgang Schwotzer + * + * 01/2000 added support for new joystick driver + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_JOYSTICK_H +#include +#define JOYDEV "/dev/js%d" +#endif +#ifdef HAVE_SYS_ERRNO_H +#include +#endif +#include "windef.h" +#include "wingdi.h" +#include "winuser.h" +#include "mmddk.h" +#include "driver.h" +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(joystick); + +#ifdef HAVE_LINUX_JOYSTICK_H + +#define MAXJOYSTICK (JOYSTICKID2 + 1) + +static struct dummy_struct* JSTCK_Dummy = NULL; + +/************************************************************************** + * JSTCK_drvOpen [internal] + */ +static DWORD JSTCK_drvOpen(LPSTR str) +{ + if (JSTCK_Dummy) + return 0; + + /* I know, this is ugly, but who cares... */ + JSTCK_Dummy = (struct dummy_struct*)1; + return 1; +} + +/************************************************************************** + * JSTCK_drvClose [internal] + */ +static DWORD JSTCK_drvClose(DWORD dwDevID) +{ + if (JSTCK_Dummy) { + JSTCK_Dummy = NULL; + return 1; + } + return 0; +} + +struct js_status +{ + int buttons; + int x; + int y; +}; + +/************************************************************************** + * JSTCK_OpenDevice [internal] + */ +static int JSTCK_OpenDevice(WORD wID) +{ + char buf[20]; + int flags; + + if (wID >= MAXJOYSTICK) return -1; + + sprintf(buf, JOYDEV, wID); +#ifdef HAVE_LINUX_22_JOYSTICK_API + flags = O_RDONLY | O_NONBLOCK; +#else + flags = O_RDONLY; +#endif + return open(buf, flags); +} + +/************************************************************************** + * JoyGetDevCaps [MMSYSTEM.102] + */ +static LONG JSTCK_GetDevCaps(DWORD dwDevID, LPJOYCAPSA lpCaps, DWORD dwSize) +{ +#ifdef HAVE_LINUX_22_JOYSTICK_API + int dev; + char nrOfAxes; + char nrOfButtons; + char identString[MAXPNAMELEN]; + int driverVersion; +#endif + + if (dwDevID >= MAXJOYSTICK) return MMSYSERR_NODRIVER; + +#ifdef HAVE_LINUX_22_JOYSTICK_API + + if ((dev = JSTCK_OpenDevice(dwDevID)) < 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; + strncpy(lpCaps->szPname, identString, 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; + lpCaps->wNumButtons = nrOfButtons; + if (dwSize == sizeof(JOYCAPSA)) { + /* since we supose ntOfAxes <= 6 in the following code, do it explicitely */ + if (nrOfAxes > 6) nrOfAxes = 6; + /* complete 95 structure */ + lpCaps->wRmin = 0; + lpCaps->wRmax = nrOfAxes >= 4 ? 0xFFFF : 0; + lpCaps->wUmin = 0; + lpCaps->wUmax = nrOfAxes >= 5 ? 0xFFFF : 0; + lpCaps->wVmin = 0; + lpCaps->wVmax = nrOfAxes >= 6 ? 0xFFFF : 0; + lpCaps->wMaxAxes = 6; /* same as MS Joystick Driver */ + lpCaps->wNumAxes = nrOfAxes; /* nr of axes in use */ + lpCaps->wMaxButtons = 32; /* same as MS Joystick Driver */ + strcpy(lpCaps->szRegKey, ""); + strcpy(lpCaps->szOEMVxD, ""); + lpCaps->wCaps = 0; + switch(nrOfAxes) { + case 6: lpCaps->wCaps |= JOYCAPS_HASV; + case 5: lpCaps->wCaps |= JOYCAPS_HASU; + case 4: lpCaps->wCaps |= JOYCAPS_HASR; + case 3: lpCaps->wCaps |= JOYCAPS_HASZ; + /* FIXME: don't know how to detect for + JOYCAPS_HASPOV, JOYCAPS_POV4DIR, JOYCAPS_POVCTS */ + } + } + close(dev); + +#else + lpCaps->wMid = MM_MICROSOFT; + lpCaps->wPid = MM_PC_JOYSTICK; + strcpy(lpCaps->szPname, "WineJoy"); /* 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(JOYCAPSA)) { + /* 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; + strcpy(lpCaps->szRegKey,""); + strcpy(lpCaps->szOEMVxD,""); + } +#endif + + return JOYERR_NOERROR; +} + +/************************************************************************** + * JSTCK_GetPos [internal] + */ +static LONG JSTCK_GetPosEx(DWORD dwDevID, LPJOYINFOEX lpInfo) +{ + int dev; +#ifdef HAVE_LINUX_22_JOYSTICK_API + struct js_event ev; +#else + struct js_status js; + int dev_stat; +#endif + + if ((dev = JSTCK_OpenDevice(dwDevID)) < 0) return JOYERR_PARMS; + +#ifdef HAVE_LINUX_22_JOYSTICK_API + /* After opening the device it's state can be + read with JS_EVENT_INIT flag */ + while ((read(dev, &ev, sizeof(struct js_event))) > 0) { + if (ev.type == (JS_EVENT_AXIS | JS_EVENT_INIT)) { + switch (ev.number) { + case 0: + if (lpInfo->dwFlags & JOY_RETURNX) + lpInfo->dwXpos = ev.value + 32767; + break; + case 1: + if (lpInfo->dwFlags & JOY_RETURNY) + lpInfo->dwYpos = ev.value + 32767; + break; + case 2: + if (lpInfo->dwFlags & JOY_RETURNZ) + lpInfo->dwZpos = ev.value + 32767; + break; + case 3: + if (lpInfo->dwFlags & JOY_RETURNR) + lpInfo->dwRpos = ev.value + 32767; + case 4: + if (lpInfo->dwFlags & JOY_RETURNU) + lpInfo->dwUpos = ev.value + 32767; + case 5: + if (lpInfo->dwFlags & JOY_RETURNV) + lpInfo->dwVpos = ev.value + 32767; + break; + default: + FIXME("Unknown joystick event '%d'\n", ev.number); + } + } else if (ev.type == (JS_EVENT_BUTTON | JS_EVENT_INIT)) { + if (lpInfo->dwFlags & JOY_RETURNBUTTONS) { + if (ev.value) { + lpInfo->dwButtons |= (1 << ev.number); + /* FIXME: what to do for this field when + * multiple buttons are depressed ? + */ + lpInfo->dwButtonNumber = ev.number + 1; + } + } + } + } + /* EAGAIN is returned when the queue is empty */ + if (errno != EAGAIN) { + /* FIXME: error should not be ignored */ + ERR("Error while reading joystick state (%d)\n", errno); + } +#else + dev_stat = read(dev, &js, sizeof(js)); + if (dev_stat != sizeof(js)) { + close(dev); + 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 + + close(dev); + + TRACE("x: %ld, y: %ld, z: %ld, r: %ld, u: %ld, v: %ld, buttons: 0x%04x, flags: 0x%04x\n", + lpInfo->dwXpos, lpInfo->dwYpos, lpInfo->dwZpos, + lpInfo->dwRpos, lpInfo->dwUpos, lpInfo->dwVpos, + (unsigned int)lpInfo->dwButtons, + (unsigned int)lpInfo->dwFlags); + + return JOYERR_NOERROR; +} + +/************************************************************************** + * JSTCK_GetPos [internal] + */ +static LONG JSTCK_GetPos(DWORD 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; +} + +/************************************************************************** + * JSTCK_DriverProc [internal] + */ +LONG CALLBACK JSTCK_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, + DWORD dwParam1, DWORD 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); + 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 JDD_GETNUMDEVS: return MAXJOYSTICK; + case JDD_GETDEVCAPS: return JSTCK_GetDevCaps(dwDevID, (LPJOYCAPSA)dwParam1, dwParam2); + case JDD_GETPOS: return JSTCK_GetPos(dwDevID, (LPJOYINFO)dwParam1); + case JDD_SETCALIBRATION: + case JDD_CONFIGCHANGED: return JOYERR_NOCANDO; + case JDD_GETPOSEX: return JSTCK_GetPosEx(dwDevID, (LPJOYINFOEX)dwParam1); + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} + +#else + +/************************************************************************** + * JSTCK_DriverProc [internal] + */ +LONG CALLBACK JSTCK_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, + DWORD dwParam1, DWORD dwParam2) +{ + /* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */ + /* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */ + + switch(wMsg) { + case DRV_LOAD: + case DRV_FREE: + case DRV_OPEN: + case DRV_CLOSE: + case DRV_ENABLE: + case DRV_DISABLE: + case DRV_QUERYCONFIGURE: return 0; + 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; + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} + +#endif diff --git a/dlls/winmm/joystick/joystick.spec b/dlls/winmm/joystick/joystick.spec new file mode 100644 index 00000000000..bea6d1a1e6d --- /dev/null +++ b/dlls/winmm/joystick/joystick.spec @@ -0,0 +1,5 @@ +name joystick +file joystick.drv +type win32 + + 1 stdcall DriverProc(long long long long long) JSTCK_DriverProc diff --git a/include/debugdefs.h b/include/debugdefs.h index 86b8b6ae166..3d08eba0d07 100644 --- a/include/debugdefs.h +++ b/include/debugdefs.h @@ -71,6 +71,7 @@ char dbch_int21[] = "\003int21"; char dbch_int31[] = "\003int31"; char dbch_io[] = "\003io"; char dbch_ipaddress[] = "\003ipaddress"; +char dbch_joystick[] = "\003joystick"; char dbch_key[] = "\003key"; char dbch_keyboard[] = "\003keyboard"; char dbch_ldt[] = "\003ldt"; @@ -169,7 +170,7 @@ char dbch_wnet[] = "\003wnet"; char dbch_x11[] = "\003x11"; char dbch_x11drv[] = "\003x11drv"; -#define DEBUG_CHANNEL_COUNT 162 +#define DEBUG_CHANNEL_COUNT 163 static char * const debug_channels[DEBUG_CHANNEL_COUNT] = { dbch_accel, @@ -237,6 +238,7 @@ static char * const debug_channels[DEBUG_CHANNEL_COUNT] = { dbch_int31, dbch_io, dbch_ipaddress, + dbch_joystick, dbch_key, dbch_keyboard, dbch_ldt, diff --git a/include/message.h b/include/message.h index fd86651e805..2c789e47395 100644 --- a/include/message.h +++ b/include/message.h @@ -42,6 +42,4 @@ extern BOOL EVENT_CheckFocus( void ); extern HWND EVENT_Capture( HWND, INT16 ); -extern void joySendMessages(void); - #endif /* __WINE_MESSAGE_H */ diff --git a/include/mmddk.h b/include/mmddk.h index 6af547a3bad..a1de5d40f9b 100644 --- a/include/mmddk.h +++ b/include/mmddk.h @@ -132,12 +132,16 @@ typedef struct { #define MIDM_RESET 62 -#define AUXM_INIT DRVM_INIT +#define AUXM_INIT DRVM_INIT #define AUXDM_GETNUMDEVS 3 #define AUXDM_GETDEVCAPS 4 #define AUXDM_GETVOLUME 5 #define AUXDM_SETVOLUME 6 +#define MXDM_INIT DRVM_INIT +#define MXDM_USER DRVM_USER +#define MXDM_MAPPER DRVM_MAPPER + #define MXDM_GETNUMDEVS 1 #define MXDM_GETDEVCAPS 2 #define MXDM_OPEN 3 @@ -147,6 +151,144 @@ typedef struct { #define MXDM_GETCONTROLDETAILS 7 #define MXDM_SETCONTROLDETAILS 8 +/* pre-defined joystick types */ +#define JOY_HW_NONE 0 +#define JOY_HW_CUSTOM 1 +#define JOY_HW_2A_2B_GENERIC 2 +#define JOY_HW_2A_4B_GENERIC 3 +#define JOY_HW_2B_GAMEPAD 4 +#define JOY_HW_2B_FLIGHTYOKE 5 +#define JOY_HW_2B_FLIGHTYOKETHROTTLE 6 +#define JOY_HW_3A_2B_GENERIC 7 +#define JOY_HW_3A_4B_GENERIC 8 +#define JOY_HW_4B_GAMEPAD 9 +#define JOY_HW_4B_FLIGHTYOKE 10 +#define JOY_HW_4B_FLIGHTYOKETHROTTLE 11 +#define JOY_HW_LASTENTRY 12 + +/* calibration flags */ +#define JOY_ISCAL_XY 0x00000001l /* XY are calibrated */ +#define JOY_ISCAL_Z 0x00000002l /* Z is calibrated */ +#define JOY_ISCAL_R 0x00000004l /* R is calibrated */ +#define JOY_ISCAL_U 0x00000008l /* U is calibrated */ +#define JOY_ISCAL_V 0x00000010l /* V is calibrated */ +#define JOY_ISCAL_POV 0x00000020l /* POV is calibrated */ + +/* point of view constants */ +#define JOY_POV_NUMDIRS 4 +#define JOY_POVVAL_FORWARD 0 +#define JOY_POVVAL_BACKWARD 1 +#define JOY_POVVAL_LEFT 2 +#define JOY_POVVAL_RIGHT 3 + +/* Specific settings for joystick hardware */ +#define JOY_HWS_HASZ 0x00000001l /* has Z info? */ +#define JOY_HWS_HASPOV 0x00000002l /* point of view hat present */ +#define JOY_HWS_POVISBUTTONCOMBOS 0x00000004l /* pov done through combo of buttons */ +#define JOY_HWS_POVISPOLL 0x00000008l /* pov done through polling */ +#define JOY_HWS_ISYOKE 0x00000010l /* joystick is a flight yoke */ +#define JOY_HWS_ISGAMEPAD 0x00000020l /* joystick is a game pad */ +#define JOY_HWS_ISCARCTRL 0x00000040l /* joystick is a car controller */ +/* X defaults to J1 X axis */ +#define JOY_HWS_XISJ1Y 0x00000080l /* X is on J1 Y axis */ +#define JOY_HWS_XISJ2X 0x00000100l /* X is on J2 X axis */ +#define JOY_HWS_XISJ2Y 0x00000200l /* X is on J2 Y axis */ +/* Y defaults to J1 Y axis */ +#define JOY_HWS_YISJ1X 0x00000400l /* Y is on J1 X axis */ +#define JOY_HWS_YISJ2X 0x00000800l /* Y is on J2 X axis */ +#define JOY_HWS_YISJ2Y 0x00001000l /* Y is on J2 Y axis */ +/* Z defaults to J2 Y axis */ +#define JOY_HWS_ZISJ1X 0x00002000l /* Z is on J1 X axis */ +#define JOY_HWS_ZISJ1Y 0x00004000l /* Z is on J1 Y axis */ +#define JOY_HWS_ZISJ2X 0x00008000l /* Z is on J2 X axis */ +/* POV defaults to J2 Y axis, if it is not button based */ +#define JOY_HWS_POVISJ1X 0x00010000l /* pov done through J1 X axis */ +#define JOY_HWS_POVISJ1Y 0x00020000l /* pov done through J1 Y axis */ +#define JOY_HWS_POVISJ2X 0x00040000l /* pov done through J2 X axis */ +/* R defaults to J2 X axis */ +#define JOY_HWS_HASR 0x00080000l /* has R (4th axis) info */ +#define JOY_HWS_RISJ1X 0x00100000l /* R done through J1 X axis */ +#define JOY_HWS_RISJ1Y 0x00200000l /* R done through J1 Y axis */ +#define JOY_HWS_RISJ2Y 0x00400000l /* R done through J2 X axis */ +/* U & V for future hardware */ +#define JOY_HWS_HASU 0x00800000l /* has U (5th axis) info */ +#define JOY_HWS_HASV 0x01000000l /* has V (6th axis) info */ + +/* Usage settings */ +#define JOY_US_HASRUDDER 0x00000001l /* joystick configured with rudder */ +#define JOY_US_PRESENT 0x00000002l /* is joystick actually present? */ +#define JOY_US_ISOEM 0x00000004l /* joystick is an OEM defined type */ + + +/* struct for storing x,y, z, and rudder values */ +typedef struct joypos_tag { + DWORD dwX; + DWORD dwY; + DWORD dwZ; + DWORD dwR; + DWORD dwU; + DWORD dwV; +} JOYPOS, *LPJOYPOS; + +/* struct for storing ranges */ +typedef struct joyrange_tag { + JOYPOS jpMin; + JOYPOS jpMax; + JOYPOS jpCenter; +} JOYRANGE,*LPJOYRANGE; + +typedef struct joyreguservalues_tag { + DWORD dwTimeOut; /* value at which to timeout joystick polling */ + JOYRANGE jrvRanges; /* range of values app wants returned for axes */ + JOYPOS jpDeadZone; /* area around center to be considered + as "dead". specified as a percentage + (0-100). Only X & Y handled by system driver */ +} JOYREGUSERVALUES, *LPJOYREGUSERVALUES; + +typedef struct joyreghwsettings_tag { + DWORD dwFlags; + DWORD dwNumButtons; /* number of buttons */ +} JOYREGHWSETTINGS, *LPJOYHWSETTINGS; + +/* range of values returned by the hardware (filled in by calibration) */ +typedef struct joyreghwvalues_tag { + JOYRANGE jrvHardware; /* values returned by hardware */ + DWORD dwPOVValues[JOY_POV_NUMDIRS];/* POV values returned by hardware */ + DWORD dwCalFlags; /* what has been calibrated */ +} JOYREGHWVALUES, *LPJOYREGHWVALUES; + +/* hardware configuration */ +typedef struct joyreghwconfig_tag { + JOYREGHWSETTINGS hws; /* hardware settings */ + DWORD dwUsageSettings;/* usage settings */ + JOYREGHWVALUES hwv; /* values returned by hardware */ + DWORD dwType; /* type of joystick */ + DWORD dwReserved; /* reserved for OEM drivers */ +} JOYREGHWCONFIG, *LPJOYREGHWCONFIG; + +/* joystick calibration info structure */ +typedef struct joycalibrate_tag { + UINT wXbase; + UINT wXdelta; + UINT wYbase; + UINT wYdelta; + UINT wZbase; + UINT wZdelta; +} JOYCALIBRATE; +typedef JOYCALIBRATE *LPJOYCALIBRATE; + +/* prototype for joystick message function */ +typedef UINT (CALLBACK JOYDEVMSGPROC)(DWORD dwID, UINT uMessage, LPARAM lParam1, LPARAM lParam2); +typedef JOYDEVMSGPROC *LPJOYDEVMSGPROC; + +/* messages sent to joystick driver's DriverProc() function */ +#define JDD_GETNUMDEVS (DRV_RESERVED + 0x0001) +#define JDD_GETDEVCAPS (DRV_RESERVED + 0x0002) +#define JDD_GETPOS (DRV_RESERVED + 0x0101) +#define JDD_SETCALIBRATION (DRV_RESERVED + 0x0102) +#define JDD_CONFIGCHANGED (DRV_RESERVED + 0x0103) +#define JDD_GETPOSEX (DRV_RESERVED + 0x0104) + #define MCI_MAX_DEVICE_TYPE_LENGTH 80 #define MCI_FALSE (MCI_STRING_OFFSET + 19) diff --git a/windows/message.c b/windows/message.c index 78f25783d15..2337bca8224 100644 --- a/windows/message.c +++ b/windows/message.c @@ -577,9 +577,6 @@ static BOOL MSG_PeekHardwareMsg( MSG *msg, HWND hwnd, DWORD first, DWORD last, QMSG *nextqmsg, *qmsg = 0; BOOL bRet = FALSE; - /* FIXME: there has to be a better way to do this */ - joySendMessages(); - EnterCriticalSection(&sysMsgQueue->cSection); /* Loop through the Q and translate the message we wish to process