| /* | |
| * 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. | |
| */ | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <fcntl.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/errno.h> | |
| #include "windows.h" | |
| #include "ldt.h" | |
| #include "user.h" | |
| #include "driver.h" | |
| #include "mmsystem.h" | |
| #include "debug.h" | |
| #define MAXJOYDRIVERS 4 | |
| static int count_use[MAXJOYDRIVERS] = {0, 0, 0, 0}; | |
| static int dev_stat; | |
| static int joy_nr_open = 0; | |
| static BOOL16 joyCaptured = FALSE; | |
| static HWND16 CaptureWnd[MAXJOYDRIVERS] = {0, 0}; | |
| static int joy_dev[MAXJOYDRIVERS] = {-1, -1,-1,-1}; | |
| static JOYINFO16 joyCapData[MAXJOYDRIVERS]; | |
| static unsigned int joy_threshold[MAXJOYDRIVERS] = {0, 0, 0, 0}; | |
| struct js_status | |
| { | |
| int buttons; | |
| int x; | |
| int y; | |
| }; | |
| /************************************************************************** | |
| * joyOpenDriver [internal] | |
| */ | |
| BOOL16 joyOpenDriver(WORD wID) | |
| { | |
| char dev_name[] = "/dev/js%d"; | |
| char buf[20]; | |
| if (joy_dev[wID] >= 0) return TRUE; | |
| sprintf(buf,dev_name,wID); | |
| if ((joy_dev[wID] = open(buf, O_RDONLY)) >= 0) { | |
| joy_nr_open++; | |
| return TRUE; | |
| } else | |
| return FALSE; | |
| } | |
| /************************************************************************** | |
| * joyCloseDriver [internal] | |
| */ | |
| void joyCloseDriver(WORD wID) | |
| { | |
| if (joy_dev[wID] >= 0) { | |
| close(joy_dev[wID]); | |
| joy_dev[wID] = -1; | |
| joy_nr_open--; | |
| } | |
| } | |
| /************************************************************************** | |
| * joySendMessages [internal] | |
| */ | |
| void joySendMessages(void) | |
| { | |
| int joy; | |
| struct js_status js; | |
| if (joy_nr_open) | |
| { | |
| for (joy=0; joy < MAXJOYDRIVERS; 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(mmsys, " --\n"); | |
| for (joy=0; joy < MAXJOYDRIVERS; joy++) { | |
| if (joyOpenDriver(joy) == FALSE) continue; | |
| dev_stat = read(joy_dev[joy], &js, sizeof(js)); | |
| if (dev_stat == sizeof(js)) { | |
| js.x = js.x*37; | |
| js.y = js.y*37; | |
| if ((joyCapData[joy].wXpos != js.x) || (joyCapData[joy].wYpos != js.y)) { | |
| SendMessage32A(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) | |
| SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONDOWN + joy, ButtonChanged, MAKELONG(js.x, js.y)); | |
| else | |
| if (joyCapData[joy].wButtons > js.buttons) | |
| SendMessage32A(CaptureWnd[joy], MM_JOY1BUTTONUP | |
| + joy, ButtonChanged, MAKELONG(js.x, js.y)); | |
| joyCapData[joy].wButtons = js.buttons; | |
| } | |
| } | |
| } | |
| } | |
| /************************************************************************** | |
| * JoyGetNumDevs [MMSYSTEM.101] | |
| */ | |
| UINT32 WINAPI joyGetNumDevs32(void) | |
| { | |
| return joyGetNumDevs16(); | |
| } | |
| /************************************************************************** | |
| * JoyGetNumDevs [MMSYSTEM.101] | |
| */ | |
| UINT16 WINAPI joyGetNumDevs16(void) | |
| { | |
| int joy; | |
| UINT16 joy_cnt = 0; | |
| for (joy=0; joy<MAXJOYDRIVERS; joy++) | |
| if (joyOpenDriver(joy) == TRUE) { | |
| joyCloseDriver(joy); | |
| joy_cnt++; | |
| } | |
| TRACE(mmsys, "returning %d\n", joy_cnt); | |
| if (!joy_cnt) ERR(mmsys, "No joystick found - " | |
| "perhaps get joystick-0.8.0.tar.gz and load" | |
| "it as module or use Linux >= 2.1.45 to be " | |
| "able to use joysticks.\n"); | |
| return joy_cnt; | |
| } | |
| /************************************************************************** | |
| * JoyGetDevCaps [WINMM.27] | |
| */ | |
| MMRESULT32 WINAPI joyGetDevCaps32A(UINT32 wID, LPJOYCAPS32A lpCaps,UINT32 wSize) | |
| { | |
| JOYCAPS16 jc16; | |
| MMRESULT16 ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16)); | |
| lpCaps->wMid = jc16.wMid; | |
| lpCaps->wPid = jc16.wPid; | |
| lstrcpy32A(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; | |
| lstrcpy32A(lpCaps->szRegKey,jc16.szRegKey); | |
| lstrcpy32A(lpCaps->szOEMVxD,jc16.szOEMVxD); | |
| return ret; | |
| } | |
| /************************************************************************** | |
| * JoyGetDevCaps [WINMM.28] | |
| */ | |
| MMRESULT32 WINAPI joyGetDevCaps32W(UINT32 wID, LPJOYCAPS32W lpCaps,UINT32 wSize) | |
| { | |
| JOYCAPS16 jc16; | |
| MMRESULT16 ret = joyGetDevCaps16(wID,&jc16,sizeof(jc16)); | |
| 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; | |
| } | |
| /************************************************************************** | |
| * JoyGetDevCaps [MMSYSTEM.102] | |
| */ | |
| MMRESULT16 WINAPI joyGetDevCaps16(UINT16 wID, LPJOYCAPS16 lpCaps, UINT16 wSize) | |
| { | |
| TRACE(mmsys, "(%04X, %p, %d);\n", | |
| wID, lpCaps, wSize); | |
| if (joyOpenDriver(wID) == TRUE) { | |
| lpCaps->wMid = MM_MICROSOFT; | |
| lpCaps->wPid = MM_PC_JOYSTICK; | |
| strcpy(lpCaps->szPname, "WineJoy"); /* joystick product name */ | |
| lpCaps->wXmin = 0; /* FIXME */ | |
| lpCaps->wXmax = 0xffff; | |
| lpCaps->wYmin = 0; | |
| lpCaps->wYmax = 0xffff; | |
| lpCaps->wZmin = 0; | |
| lpCaps->wZmax = 0xffff; | |
| lpCaps->wNumButtons = 2; | |
| lpCaps->wPeriodMin = 0; | |
| lpCaps->wPeriodMax = 50; /* FIXME end */ | |
| if (wSize == sizeof(JOYCAPS16)) { | |
| /* complete 95 structure */ | |
| lpCaps->wRmin = 0; | |
| lpCaps->wRmax = 0xffff; | |
| lpCaps->wUmin = 0; | |
| lpCaps->wUmax = 0xffff; | |
| lpCaps->wVmin = 0; | |
| lpCaps->wVmax = 0xffff; | |
| lpCaps->wCaps = 0; | |
| lpCaps->wMaxAxes = 6; | |
| lpCaps->wNumAxes = 2; | |
| lpCaps->wMaxButtons = 3; | |
| strcpy(lpCaps->szRegKey,""); | |
| strcpy(lpCaps->szOEMVxD,""); | |
| } | |
| joyCloseDriver(wID); | |
| return JOYERR_NOERROR; | |
| } | |
| else | |
| return MMSYSERR_NODRIVER; | |
| } | |
| /************************************************************************** | |
| * JoyGetPosEx [WINMM.31] | |
| */ | |
| MMRESULT32 WINAPI joyGetPosEx(UINT32 wID, LPJOYINFOEX lpInfo) | |
| { | |
| /* FIXME: implement it */ | |
| return MMSYSERR_NODRIVER; | |
| } | |
| /************************************************************************** | |
| * JoyGetPos [WINMM.30] | |
| */ | |
| MMRESULT32 WINAPI joyGetPos32(UINT32 wID, LPJOYINFO32 lpInfo) | |
| { | |
| JOYINFO16 ji; | |
| MMRESULT16 ret = joyGetPos16(wID,&ji); | |
| lpInfo->wXpos = ji.wXpos; | |
| lpInfo->wYpos = ji.wYpos; | |
| lpInfo->wZpos = ji.wZpos; | |
| lpInfo->wButtons = ji.wButtons; | |
| return ret; | |
| } | |
| /************************************************************************** | |
| * JoyGetPos [MMSYSTEM.103] | |
| */ | |
| MMRESULT16 WINAPI joyGetPos16(UINT16 wID, LPJOYINFO16 lpInfo) | |
| { | |
| struct js_status js; | |
| TRACE(mmsys, "(%04X, %p)\n", wID, lpInfo); | |
| if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER; | |
| 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*37; | |
| js.y = js.y*37; | |
| lpInfo->wXpos = js.x; /* FIXME: perhaps multiply it somehow ? */ | |
| lpInfo->wYpos = js.y; | |
| lpInfo->wZpos = 0; /* FIXME: Don't know what to do with this value as joystick driver doesn't provide a Z value */ | |
| lpInfo->wButtons = js.buttons; | |
| TRACE(mmsys, "x: %d, y: %d, buttons: %d\n", js.x, js.y, js.buttons); | |
| return JOYERR_NOERROR; | |
| } | |
| /************************************************************************** | |
| * JoyGetThreshold [WINMM.32] | |
| */ | |
| MMRESULT32 WINAPI joyGetThreshold32(UINT32 wID, LPUINT32 lpThreshold) | |
| { | |
| UINT16 thresh; | |
| MMRESULT16 ret = joyGetThreshold16(wID,&thresh); | |
| *lpThreshold = thresh; | |
| return ret; | |
| } | |
| /************************************************************************** | |
| * JoyGetThreshold [MMSYSTEM.104] | |
| */ | |
| MMRESULT16 WINAPI joyGetThreshold16(UINT16 wID, LPUINT16 lpThreshold) | |
| { | |
| TRACE(mmsys, "(%04X, %p);\n", wID, lpThreshold); | |
| if (wID >= MAXJOYDRIVERS) return JOYERR_PARMS; | |
| *lpThreshold = joy_threshold[wID]; | |
| return JOYERR_NOERROR; | |
| } | |
| /************************************************************************** | |
| * JoyReleaseCapture [WINMM.33] | |
| */ | |
| MMRESULT32 WINAPI joyReleaseCapture32(UINT32 wID) | |
| { | |
| return joyReleaseCapture16(wID); | |
| } | |
| /************************************************************************** | |
| * JoyReleaseCapture [MMSYSTEM.105] | |
| */ | |
| MMRESULT16 WINAPI joyReleaseCapture16(UINT16 wID) | |
| { | |
| TRACE(mmsys, "(%04X);\n", wID); | |
| joyCaptured = FALSE; | |
| joyCloseDriver(wID); | |
| joy_dev[wID] = -1; | |
| CaptureWnd[wID] = 0; | |
| return JOYERR_NOERROR; | |
| } | |
| /************************************************************************** | |
| * JoySetCapture [MMSYSTEM.106] | |
| */ | |
| MMRESULT32 WINAPI joySetCapture32(HWND32 hWnd,UINT32 wID,UINT32 wPeriod,BOOL32 bChanged) | |
| { | |
| return joySetCapture16(hWnd,wID,wPeriod,bChanged); | |
| } | |
| /************************************************************************** | |
| * JoySetCapture [MMSYSTEM.106] | |
| */ | |
| MMRESULT16 WINAPI joySetCapture16(HWND16 hWnd,UINT16 wID,UINT16 wPeriod,BOOL16 bChanged) | |
| { | |
| TRACE(mmsys, "(%04X, %04X, %d, %d);\n", | |
| hWnd, wID, wPeriod, bChanged); | |
| if (!CaptureWnd[wID]) { | |
| if (joyOpenDriver(wID) == FALSE) return MMSYSERR_NODRIVER; | |
| joyCaptured = TRUE; | |
| CaptureWnd[wID] = hWnd; | |
| return JOYERR_NOERROR; | |
| } | |
| else | |
| return JOYERR_NOCANDO; /* FIXME: what should be returned ? */ | |
| } | |
| /************************************************************************** | |
| * JoySetThreshold [WINMM.35] | |
| */ | |
| MMRESULT32 WINAPI joySetThreshold32(UINT32 wID, UINT32 wThreshold) | |
| { | |
| return joySetThreshold16(wID,wThreshold); | |
| } | |
| /************************************************************************** | |
| * JoySetThreshold [MMSYSTEM.107] | |
| */ | |
| MMRESULT16 WINAPI joySetThreshold16(UINT16 wID, UINT16 wThreshold) | |
| { | |
| TRACE(mmsys, "(%04X, %d);\n", wID, wThreshold); | |
| if (wID > 3) return JOYERR_PARMS; | |
| joy_threshold[wID] = wThreshold; | |
| return JOYERR_NOERROR; | |
| } | |
| /************************************************************************** | |
| * JoySetCalibration [MMSYSTEM.109] | |
| */ | |
| MMRESULT16 WINAPI joySetCalibration16(UINT16 wID) | |
| { | |
| FIXME(mmsys, "(%04X): stub.\n", wID); | |
| return JOYERR_NOCANDO; | |
| } |